Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


Precompiled/esptool/esptool.py ea46875d567b6765b030433f4e9c08ff3bbabf36 (ea46875d) Text, 223.22 KB

T8b949e#!/usr/bin/env python
T8b949e#
T8b949e# ESP8266 & ESP32 family ROM Bootloader Utility
T8b949e# Copyright (C) 2014-2021 Fredrik Ahlberg, Angus Gratton, Espressif Systems (Shanghai) CO LTD, other contributors as noted.
T8b949e# https://github.com/espressif/esptool
T8b949e#
T8b949e# This program is free software; you can redistribute it and/or modify it under
T8b949e# the terms of the GNU General Public License as published by the Free Software
T8b949e# Foundation; either version 2 of the License, or (at your option) any later version.
T8b949e#
T8b949e# This program is distributed in the hope that it will be useful, but WITHOUT
T8b949e# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
T8b949e# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
T8b949e#
T8b949e# You should have received a copy of the GNU General Public License along with
T8b949e# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
T8b949e# Street, Fifth Floor, Boston, MA 02110-1301 USA.

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3divisionTb4b4b4, Te6edf3print_function

Tff7b72import T7ee787argparse
Tff7b72import T7ee787base64
Tff7b72import T7ee787binascii
Tff7b72import T7ee787copy
Tff7b72import T7ee787hashlib
Tff7b72import T7ee787inspect
Tff7b72import T7ee787io
Tff7b72import T7ee787itertools
Tff7b72import T7ee787os
Tff7b72import T7ee787shlex
Tff7b72import T7ee787string
Tff7b72import T7ee787struct
Tff7b72import T7ee787sys
Tff7b72import T7ee787time
Tff7b72import T7ee787zlib

Tff7b72tryTb4b4b4:
Tff7b72import T7ee787serial
Tff7b72except Tf85149ImportErrorTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffPyserial is not installed for Tffd700%sTa5d6ff. Check the README for installation instructions.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4)Tb4b4b4)
Tff7b72raise

T8b949e# check 'serial' is 'pyserial' and not 'serial' https://github.com/espressif/esptool/issues/269
Tff7b72tryTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ffserializationTa5d6ff" Tff7b72in Te6edf3serialTff7b72.Td2a8ff__doc__ Tff7b72and Ta5d6ff"Ta5d6ffdeserializationTa5d6ff" Tff7b72in Te6edf3serialTff7b72.Td2a8ff__doc__Tb4b4b4:
Tff7b72raise Tf85149ImportErrorTb4b4b4(Ta5d6ff"""
Ta5d6ffesptool.py depends on pyserial, but there is a conflict with a currently installed package named Ta5d6ff'Ta5d6ffserialTa5d6ff'Ta5d6ff.

Ta5d6ffYou may be able to work around this by Ta5d6ff'Ta5d6ffpip uninstall serial; pip install pyserialTa5d6ff'Ta5d6ff Tffea00\
Ta5d6ffbut this may break other installed Python software that depends on Ta5d6ff'Ta5d6ffserialTa5d6ff'Ta5d6ff.

Ta5d6ffThere is no good fix for this right now, apart from configuring virtualenvs. Tffea00\
Ta5d6ffSee https://github.com/espressif/esptool/issues/269#issuecomment-385298196 for discussion of the underlying issue(s).Ta5d6ff"""Tb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4:
Tff7b72pass T8b949e# __doc__ returns None for pyserial

Tff7b72tryTb4b4b4:
Tff7b72import T7ee787serialT7ee787.T7ee787toolsT7ee787.T7ee787list_ports Tff7b72as T7ee787list_ports
Tff7b72except Tf85149ImportErrorTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffThe installed version (Tffd700%sTa5d6ff) of pyserial appears to be too old for esptool.py (Python interpreter Tffd700%sTa5d6ff). Ta5d6ff"
Ta5d6ff"Ta5d6ffCheck the README for installation instructions.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3sysTff7b72.Td2a8ffVERSIONTb4b4b4, Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4)Tb4b4b4)
Tff7b72raise
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72if Te6edf3sysTff7b72.Td2a8ffplatform Tff7b72== Ta5d6ff"Ta5d6ffdarwinTa5d6ff"Tb4b4b4:
T8b949e# swallow the exception, this is a known issue in pyserial+macOS Big Sur preview ref https://github.com/espressif/esptool/issues/540
Te6edf3list_ports Tff7b72= Tff7b72None
Tff7b72elseTb4b4b4:
Tff7b72raise


Te6edf3__version__ Tff7b72= Ta5d6ff"Ta5d6ff3.1Ta5d6ff"

Te6edf3MAX_UINT32 Tff7b72= T79c0ff0xffffffff
Te6edf3MAX_UINT24 Tff7b72= T79c0ff0xffffff

Te6edf3DEFAULT_TIMEOUT Tff7b72= T79c0ff3 T8b949e# timeout for most flash operations
Te6edf3START_FLASH_TIMEOUT Tff7b72= T79c0ff20 T8b949e# timeout for starting flash (may perform erase)
Te6edf3CHIP_ERASE_TIMEOUT Tff7b72= T79c0ff120 T8b949e# timeout for full chip erase
Te6edf3MAX_TIMEOUT Tff7b72= Te6edf3CHIP_ERASE_TIMEOUT Tff7b72* T79c0ff2 T8b949e# longest any command can run
Te6edf3SYNC_TIMEOUT Tff7b72= T79c0ff0.1 T8b949e# timeout for syncing with bootloader
Te6edf3MD5_TIMEOUT_PER_MB Tff7b72= T79c0ff8 T8b949e# timeout (per megabyte) for calculating md5sum
Te6edf3ERASE_REGION_TIMEOUT_PER_MB Tff7b72= T79c0ff30 T8b949e# timeout (per megabyte) for erasing a region
Te6edf3ERASE_WRITE_TIMEOUT_PER_MB Tff7b72= T79c0ff40 T8b949e# timeout (per megabyte) for erasing and writing data
Te6edf3MEM_END_ROM_TIMEOUT Tff7b72= T79c0ff0.05 T8b949e# special short timeout for ESP_MEM_END, as it may never respond
Te6edf3DEFAULT_SERIAL_WRITE_TIMEOUT Tff7b72= T79c0ff10 T8b949e# timeout for serial port write
Te6edf3DEFAULT_CONNECT_ATTEMPTS Tff7b72= T79c0ff7 T8b949e# default number of times to try connection


Tff7b72def Td2a8fftimeout_per_mbTb4b4b4(Te6edf3seconds_per_mbTb4b4b4, Te6edf3size_bytesTb4b4b4)Tb4b4b4:
T8b949e""" Scales timeouts which are size-specific """
Te6edf3result Tff7b72= Te6edf3seconds_per_mb Tff7b72* Tb4b4b4(Te6edf3size_bytes Tff7b72/ T79c0ff1e6Tb4b4b4)
Tff7b72if Te6edf3result Tff7b72< Te6edf3DEFAULT_TIMEOUTTb4b4b4:
Tff7b72return Te6edf3DEFAULT_TIMEOUT
Tff7b72return Te6edf3result


Tff7b72def Td2a8ff_chip_to_rom_loaderTb4b4b4(Te6edf3chipTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4{
Ta5d6ff'Ta5d6ffesp8266Ta5d6ff'Tb4b4b4: Te6edf3ESP8266ROMTb4b4b4,
Ta5d6ff'Ta5d6ffesp32Ta5d6ff'Tb4b4b4: Te6edf3ESP32ROMTb4b4b4,
Ta5d6ff'Ta5d6ffesp32s2Ta5d6ff'Tb4b4b4: Te6edf3ESP32S2ROMTb4b4b4,
Ta5d6ff'Ta5d6ffesp32s3beta2Ta5d6ff'Tb4b4b4: Te6edf3ESP32S3BETA2ROMTb4b4b4,
Ta5d6ff'Ta5d6ffesp32s3beta3Ta5d6ff'Tb4b4b4: Te6edf3ESP32S3BETA3ROMTb4b4b4,
Ta5d6ff'Ta5d6ffesp32c3Ta5d6ff'Tb4b4b4: Te6edf3ESP32C3ROMTb4b4b4,
Ta5d6ff'Ta5d6ffesp32c6betaTa5d6ff'Tb4b4b4: Te6edf3ESP32C6BETAROMTb4b4b4,
Tb4b4b4}Tb4b4b4[Te6edf3chipTb4b4b4]


Tff7b72def Td2a8ffget_default_connected_deviceTb4b4b4(Te6edf3serial_listTb4b4b4, Te6edf3portTb4b4b4, Te6edf3connect_attemptsTb4b4b4, Te6edf3initial_baudTb4b4b4, Te6edf3chipTff7b72=Ta5d6ff'Ta5d6ffautoTa5d6ff'Tb4b4b4, Te6edf3traceTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3beforeTff7b72=Ta5d6ff'Ta5d6ffdefault_resetTa5d6ff'Tb4b4b4)Tb4b4b4:
Te6edf3_esp Tff7b72= Tff7b72None
Tff7b72for Te6edf3each_port Tff7b72in Tffa657reversedTb4b4b4(Te6edf3serial_listTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffSerial port Tffd700%sTa5d6ff" Tff7b72% Te6edf3each_portTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3chip Tff7b72== Ta5d6ff'Ta5d6ffautoTa5d6ff'Tb4b4b4:
Te6edf3_esp Tff7b72= Te6edf3ESPLoaderTff7b72.Td2a8ffdetect_chipTb4b4b4(Te6edf3each_portTb4b4b4, Te6edf3initial_baudTb4b4b4, Te6edf3beforeTb4b4b4, Te6edf3traceTb4b4b4,
Te6edf3connect_attemptsTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3chip_class Tff7b72= Te6edf3_chip_to_rom_loaderTb4b4b4(Te6edf3chipTb4b4b4)
Te6edf3_esp Tff7b72= Te6edf3chip_classTb4b4b4(Te6edf3each_portTb4b4b4, Te6edf3initial_baudTb4b4b4, Te6edf3traceTb4b4b4)
Te6edf3_espTff7b72.Td2a8ffconnectTb4b4b4(Te6edf3beforeTb4b4b4, Te6edf3connect_attemptsTb4b4b4)
Tff7b72break
Tff7b72except Tb4b4b4(Te6edf3FatalErrorTb4b4b4, Tf85149OSErrorTb4b4b4) Tff7b72as Te6edf3errTb4b4b4:
Tff7b72if Te6edf3port Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72raise
Tffa657printTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff failed to connect: Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3each_portTb4b4b4, Te6edf3errTb4b4b4)Tb4b4b4)
Te6edf3_esp Tff7b72= Tff7b72None
Tff7b72return Te6edf3_esp


Te6edf3DETECTED_FLASH_SIZES Tff7b72= Tb4b4b4{T79c0ff0x12Tb4b4b4: Ta5d6ff'Ta5d6ff256KBTa5d6ff'Tb4b4b4, T79c0ff0x13Tb4b4b4: Ta5d6ff'Ta5d6ff512KBTa5d6ff'Tb4b4b4, T79c0ff0x14Tb4b4b4: Ta5d6ff'Ta5d6ff1MBTa5d6ff'Tb4b4b4,
T79c0ff0x15Tb4b4b4: Ta5d6ff'Ta5d6ff2MBTa5d6ff'Tb4b4b4, T79c0ff0x16Tb4b4b4: Ta5d6ff'Ta5d6ff4MBTa5d6ff'Tb4b4b4, T79c0ff0x17Tb4b4b4: Ta5d6ff'Ta5d6ff8MBTa5d6ff'Tb4b4b4,
T79c0ff0x18Tb4b4b4: Ta5d6ff'Ta5d6ff16MBTa5d6ff'Tb4b4b4, T79c0ff0x19Tb4b4b4: Ta5d6ff'Ta5d6ff32MBTa5d6ff'Tb4b4b4, T79c0ff0x1aTb4b4b4: Ta5d6ff'Ta5d6ff64MBTa5d6ff'Tb4b4b4}


Tff7b72def Td2a8ffcheck_supported_functionTb4b4b4(Te6edf3funcTb4b4b4, Te6edf3check_funcTb4b4b4)Tb4b4b4:
T8b949e"""
Decorator implementation that wraps a check around an ESPLoader
bootloader function to check if it's supported.

This is used to capture the multidimensional differences in
functionality between the ESP8266 & ESP32/32S2/32S3/32C3 ROM loaders, and the
software stub that runs on both. Not possible to do this cleanly
via inheritance alone.
"""
Tff7b72def Td2a8ffinnerTb4b4b4(Tff7b72*Te6edf3argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)Tb4b4b4:
Te6edf3obj Tff7b72= Te6edf3argsTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72if Te6edf3check_funcTb4b4b4(Te6edf3objTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3funcTb4b4b4(Tff7b72*Te6edf3argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3NotImplementedInROMErrorTb4b4b4(Te6edf3objTb4b4b4, Te6edf3funcTb4b4b4)
Tff7b72return Te6edf3inner


Tff7b72def Td2a8ffstub_function_onlyTb4b4b4(Te6edf3funcTb4b4b4)Tb4b4b4:
T8b949e""" Attribute for a function only supported in the software stub loader """
Tff7b72return Te6edf3check_supported_functionTb4b4b4(Te6edf3funcTb4b4b4, Tff7b72lambda Te6edf3oTb4b4b4: Te6edf3oTff7b72.Td2a8ffIS_STUBTb4b4b4)


Tff7b72def Td2a8ffstub_and_esp32_function_onlyTb4b4b4(Te6edf3funcTb4b4b4)Tb4b4b4:
T8b949e""" Attribute for a function only supported by software stubs or ESP32/32S2/32S3/32C3 ROM """
Tff7b72return Te6edf3check_supported_functionTb4b4b4(Te6edf3funcTb4b4b4, Tff7b72lambda Te6edf3oTb4b4b4: Te6edf3oTff7b72.Td2a8ffIS_STUB Tff7b72or Tffa657isinstanceTb4b4b4(Te6edf3oTb4b4b4, Te6edf3ESP32ROMTb4b4b4)Tb4b4b4)


Te6edf3PYTHON2 Tff7b72= Te6edf3sysTff7b72.Td2a8ffversion_infoTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72< T79c0ff3 T8b949e# True if on pre-Python 3

T8b949e# Function to return nth byte of a bitstring
T8b949e# Different behaviour on Python 2 vs 3
Tff7b72if Te6edf3PYTHON2Tb4b4b4:
Tff7b72def Td2a8ffbyteTb4b4b4(Te6edf3bitstrTb4b4b4, Te6edf3indexTb4b4b4)Tb4b4b4:
Tff7b72return Tffa657ordTb4b4b4(Te6edf3bitstrTb4b4b4[Te6edf3indexTb4b4b4]Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72def Td2a8ffbyteTb4b4b4(Te6edf3bitstrTb4b4b4, Te6edf3indexTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3bitstrTb4b4b4[Te6edf3indexTb4b4b4]

T8b949e# Provide a 'basestring' class on Python 3
Tff7b72tryTb4b4b4:
Te6edf3basestring
Tff7b72except Tf85149NameErrorTb4b4b4:
Te6edf3basestring Tff7b72= Tffa657str


Tff7b72def Td2a8ffprint_overwriteTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3last_lineTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e""" Print a message, overwriting the currently printed line.

If last_line is False, don't append a newline at the end (expecting another subsequent call will overwrite this one.)

After a sequence of calls with last_line=False, call once with last_line=True.

If output is not a TTY (for example redirected a pipe), no overwriting happens and this function is the same as print().
"""
Tff7b72if Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffisattyTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\rTffd700%sTa5d6ff" Tff7b72% Te6edf3messageTb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Tffea00\nTa5d6ff' Tff7b72if Te6edf3last_line Tff7b72else Ta5d6ff'Ta5d6ff'Tb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(Te6edf3messageTb4b4b4)


Tff7b72def Td2a8ff_mask_to_shiftTb4b4b4(Te6edf3maskTb4b4b4)Tb4b4b4:
T8b949e""" Return the index of the least significant bit in the mask """
Te6edf3shift Tff7b72= T79c0ff0
Tff7b72while Te6edf3mask Tff7b72& T79c0ff0x1 Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3shift Tff7b72+Tff7b72= T79c0ff1
Te6edf3mask Tff7b72>>Tff7b72= T79c0ff1
Tff7b72return Te6edf3shift


Tff7b72def Td2a8ffesp8266_function_onlyTb4b4b4(Te6edf3funcTb4b4b4)Tb4b4b4:
T8b949e""" Attribute for a function only supported on ESP8266 """
Tff7b72return Te6edf3check_supported_functionTb4b4b4(Te6edf3funcTb4b4b4, Tff7b72lambda Te6edf3oTb4b4b4: Te6edf3oTff7b72.Td2a8ffCHIP_NAME Tff7b72== Ta5d6ff"Ta5d6ffESP8266Ta5d6ff"Tb4b4b4)


Tff7b72class T56d364ESPLoaderTb4b4b4(Tffa657objectTb4b4b4)Tb4b4b4:
T8b949e""" Base class providing access to ESP ROM & software stub bootloaders.
Subclasses provide ESP8266 & ESP32 specific functionality.

Don't instantiate this base class directly, either instantiate a subclass or
call ESPLoader.detect_chip() which will interrogate the chip and return the
appropriate subclass instance.

"""
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffEspressif deviceTa5d6ff"
Te6edf3IS_STUB Tff7b72= Tff7b72False

Te6edf3DEFAULT_PORT Tff7b72= Ta5d6ff"Ta5d6ff/dev/ttyUSB0Ta5d6ff"

T8b949e# Commands supported by ESP8266 ROM bootloader
Te6edf3ESP_FLASH_BEGIN Tff7b72= T79c0ff0x02
Te6edf3ESP_FLASH_DATA Tff7b72= T79c0ff0x03
Te6edf3ESP_FLASH_END Tff7b72= T79c0ff0x04
Te6edf3ESP_MEM_BEGIN Tff7b72= T79c0ff0x05
Te6edf3ESP_MEM_END Tff7b72= T79c0ff0x06
Te6edf3ESP_MEM_DATA Tff7b72= T79c0ff0x07
Te6edf3ESP_SYNC Tff7b72= T79c0ff0x08
Te6edf3ESP_WRITE_REG Tff7b72= T79c0ff0x09
Te6edf3ESP_READ_REG Tff7b72= T79c0ff0x0a

T8b949e# Some comands supported by ESP32 ROM bootloader (or -8266 w/ stub)
Te6edf3ESP_SPI_SET_PARAMS Tff7b72= T79c0ff0x0B
Te6edf3ESP_SPI_ATTACH Tff7b72= T79c0ff0x0D
Te6edf3ESP_READ_FLASH_SLOW Tff7b72= T79c0ff0x0e T8b949e# ROM only, much slower than the stub flash read
Te6edf3ESP_CHANGE_BAUDRATE Tff7b72= T79c0ff0x0F
Te6edf3ESP_FLASH_DEFL_BEGIN Tff7b72= T79c0ff0x10
Te6edf3ESP_FLASH_DEFL_DATA Tff7b72= T79c0ff0x11
Te6edf3ESP_FLASH_DEFL_END Tff7b72= T79c0ff0x12
Te6edf3ESP_SPI_FLASH_MD5 Tff7b72= T79c0ff0x13

T8b949e# Commands supported by ESP32-S2/S3/C3/C6 ROM bootloader only
Te6edf3ESP_GET_SECURITY_INFO Tff7b72= T79c0ff0x14

T8b949e# Some commands supported by stub only
Te6edf3ESP_ERASE_FLASH Tff7b72= T79c0ff0xD0
Te6edf3ESP_ERASE_REGION Tff7b72= T79c0ff0xD1
Te6edf3ESP_READ_FLASH Tff7b72= T79c0ff0xD2
Te6edf3ESP_RUN_USER_CODE Tff7b72= T79c0ff0xD3

T8b949e# Flash encryption encrypted data command
Te6edf3ESP_FLASH_ENCRYPT_DATA Tff7b72= T79c0ff0xD4

T8b949e# Response code(s) sent by ROM
Te6edf3ROM_INVALID_RECV_MSG Tff7b72= T79c0ff0x05 T8b949e# response if an invalid message is received

T8b949e# Maximum block sized for RAM and Flash writes, respectively.
Te6edf3ESP_RAM_BLOCK Tff7b72= T79c0ff0x1800

Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x400

T8b949e# Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want.
Te6edf3ESP_ROM_BAUD Tff7b72= T79c0ff115200

T8b949e# First byte of the application image
Te6edf3ESP_IMAGE_MAGIC Tff7b72= T79c0ff0xe9

T8b949e# Initial state for the checksum routine
Te6edf3ESP_CHECKSUM_MAGIC Tff7b72= T79c0ff0xef

T8b949e# Flash sector size, minimum unit of erase.
Te6edf3FLASH_SECTOR_SIZE Tff7b72= T79c0ff0x1000

Te6edf3UART_DATE_REG_ADDR Tff7b72= T79c0ff0x60000078

Te6edf3CHIP_DETECT_MAGIC_REG_ADDR Tff7b72= T79c0ff0x40001000 T8b949e# This ROM address has a different value on each chip model

Te6edf3UART_CLKDIV_MASK Tff7b72= T79c0ff0xFFFFF

T8b949e# Memory addresses
Te6edf3IROM_MAP_START Tff7b72= T79c0ff0x40200000
Te6edf3IROM_MAP_END Tff7b72= T79c0ff0x40300000

T8b949e# The number of bytes in the UART response that signify command status
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff2

T8b949e# Response to ESP_SYNC might indicate that flasher stub is running instead of the ROM bootloader
Te6edf3sync_stub_detected Tff7b72= Tff7b72False

T8b949e# Device PIDs
Te6edf3USB_JTAG_SERIAL_PID Tff7b72= T79c0ff0x1001

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3portTff7b72=Te6edf3DEFAULT_PORTTb4b4b4, Te6edf3baudTff7b72=Te6edf3ESP_ROM_BAUDTb4b4b4, Te6edf3trace_enabledTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e"""Base constructor for ESPLoader bootloader interaction

Don't call this constructor, either instantiate ESP8266ROM
or ESP32ROM, or use ESPLoader.detect_chip().

This base class has all of the instance methods for bootloader
functionality supported across various chips & stub
loaders. Subclasses replace the functions they don't support
with ones which throw NotImplementedInROMError().

"""
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Tff7b72False T8b949e# flag is set to True if esptool detects the ROM is in Secure Download Mode

Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3portTb4b4b4, Te6edf3basestringTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3serialTff7b72.Td2a8ffserial_for_urlTb4b4b4(Te6edf3portTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3port
Tff7b72selfTff7b72.Td2a8ff_slip_reader Tff7b72= Te6edf3slip_readerTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_portTb4b4b4, Tff7b72selfTff7b72.Td2a8fftraceTb4b4b4)
T8b949e# setting baud rate in a separate step is a workaround for
T8b949e# CH341 driver on some Linux versions (this opens at 9600 then
T8b949e# sets), shouldn't matter for other platforms/drivers. See
T8b949e# https://github.com/espressif/esptool/issues/44#issuecomment-107094446
Tff7b72selfTff7b72.Td2a8ff_set_port_baudrateTb4b4b4(Te6edf3baudTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3trace_enabled
T8b949e# set write timeout, to prevent esptool blocked at write forever.
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffwrite_timeout Tff7b72= Te6edf3DEFAULT_SERIAL_WRITE_TIMEOUT
Tff7b72except Tf85149NotImplementedErrorTb4b4b4:
T8b949e# no write timeout for RFC2217 ports
T8b949e# need to set the property back to None or it will continue to fail
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffwrite_timeout Tff7b72= Tff7b72None

Tf0883e@property
Tff7b72def Td2a8ffserial_portTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffport

Tff7b72def Td2a8ff_set_port_baudrateTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3baudTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffbaudrate Tff7b72= Te6edf3baud
Tff7b72except Tf85149IOErrorTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffFailed to set baud rate Tffd700%dTa5d6ff. The driver may not support this rate.Ta5d6ff" Tff7b72% Te6edf3baudTb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ffdetect_chipTb4b4b4(Te6edf3portTff7b72=Te6edf3DEFAULT_PORTTb4b4b4, Te6edf3baudTff7b72=Te6edf3ESP_ROM_BAUDTb4b4b4, Te6edf3connect_modeTff7b72=Ta5d6ff'Ta5d6ffdefault_resetTa5d6ff'Tb4b4b4, Te6edf3trace_enabledTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3connect_attemptsTff7b72=Te6edf3DEFAULT_CONNECT_ATTEMPTSTb4b4b4)Tb4b4b4:
T8b949e""" Use serial access to detect the chip type.

We use the UART's datecode register for this, it's mapped at
the same address on ESP8266 & ESP32 so we can use one
memory read and compare to the datecode register for each chip
type.

This routine automatically performs ESPLoader.connect() (passing
connect_mode parameter) as part of querying the chip.
"""
Te6edf3detect_port Tff7b72= Te6edf3ESPLoaderTb4b4b4(Te6edf3portTb4b4b4, Te6edf3baudTb4b4b4, Te6edf3trace_enabledTff7b72=Te6edf3trace_enabledTb4b4b4)
Te6edf3detect_portTff7b72.Td2a8ffconnectTb4b4b4(Te6edf3connect_modeTb4b4b4, Te6edf3connect_attemptsTb4b4b4, Te6edf3detectingTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72tryTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffDetecting chip type...Ta5d6ff'Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Ta5d6ff'Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3chip_magic_value Tff7b72= Te6edf3detect_portTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffCHIP_DETECT_MAGIC_REG_ADDRTb4b4b4)

Tff7b72for Tff7b72cls Tff7b72in Tb4b4b4[Te6edf3ESP8266ROMTb4b4b4, Te6edf3ESP32ROMTb4b4b4, Te6edf3ESP32S2ROMTb4b4b4, Te6edf3ESP32S3BETA2ROMTb4b4b4, Te6edf3ESP32S3BETA3ROMTb4b4b4, Te6edf3ESP32C3ROMTb4b4b4, Te6edf3ESP32C6BETAROMTb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3chip_magic_value Tff7b72in Tff7b72clsTff7b72.Td2a8ffCHIP_DETECT_MAGIC_VALUETb4b4b4:
T8b949e# don't connect a second time
Te6edf3inst Tff7b72= Tff7b72clsTb4b4b4(Te6edf3detect_portTff7b72.Td2a8ff_portTb4b4b4, Te6edf3baudTb4b4b4, Te6edf3trace_enabledTff7b72=Te6edf3trace_enabledTb4b4b4)
Te6edf3instTff7b72.Td2a8ff_post_connectTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff Tffd700%sTa5d6ff' Tff7b72% Te6edf3instTff7b72.Td2a8ffCHIP_NAMETb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Ta5d6ff'Tb4b4b4)
Tff7b72if Te6edf3detect_portTff7b72.Td2a8ffsync_stub_detectedTb4b4b4:
Te6edf3inst Tff7b72= Te6edf3instTff7b72.Td2a8ffSTUB_CLASSTb4b4b4(Te6edf3instTb4b4b4)
Te6edf3instTff7b72.Td2a8ffsync_stub_detected Tff7b72= Tff7b72True
Tff7b72return Te6edf3inst
Tff7b72except Te6edf3UnsupportedCommandErrorTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnsupported Command Error received. Probably this means Secure Download Mode is enabled, Ta5d6ff"
Ta5d6ff"Ta5d6ffautodetection will not work. Need to manually specify the chip.Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff'Tb4b4b4) T8b949e# end line
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnexpected CHIP magic value 0xTffd700%08xTa5d6ff. Failed to autodetect chip type.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3chip_magic_valueTb4b4b4)Tb4b4b4)

T8b949e""" Read a SLIP packet from the serial port """
Tff7b72def Td2a8ffreadTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tffa657nextTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_slip_readerTb4b4b4)

T8b949e""" Write bytes to the serial port while performing SLIP escaping """
Tff7b72def Td2a8ffwriteTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3packetTb4b4b4)Tb4b4b4:
Te6edf3buf Tff7b72= Ta5d6ffbTa5d6ff'Tffea00\xc0Ta5d6ff' \
Tff7b72+ Tb4b4b4(Te6edf3packetTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff'Tffea00\xdbTa5d6ff'Tb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\xdbTffea00\xddTa5d6ff'Tb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff'Tffea00\xc0Ta5d6ff'Tb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\xdbTffea00\xdcTa5d6ff'Tb4b4b4)Tb4b4b4) \
Tff7b72+ Ta5d6ffbTa5d6ff'Tffea00\xc0Ta5d6ff'
Tff7b72selfTff7b72.Td2a8fftraceTb4b4b4(Ta5d6ff"Ta5d6ffWrite Tffd700%dTa5d6ff bytes: Tffd700%sTa5d6ff"Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3bufTb4b4b4)Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3bufTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3bufTb4b4b4)

Tff7b72def Td2a8fftraceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3messageTb4b4b4, Tff7b72*Te6edf3format_argsTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_trace_enabledTb4b4b4:
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:

Te6edf3delta Tff7b72= Te6edf3now Tff7b72- Tff7b72selfTff7b72.Td2a8ff_last_trace
Tff7b72except Tf85149AttributeErrorTb4b4b4:
Te6edf3delta Tff7b72= T79c0ff0.0
Tff7b72selfTff7b72.Td2a8ff_last_trace Tff7b72= Te6edf3now
Te6edf3prefix Tff7b72= Ta5d6ff"Ta5d6ffTRACE +Tffd700%.3fTa5d6ff Ta5d6ff" Tff7b72% Te6edf3delta
Tffa657printTb4b4b4(Te6edf3prefix Tff7b72+ Tb4b4b4(Te6edf3message Tff7b72% Te6edf3format_argsTb4b4b4)Tb4b4b4)

T8b949e""" Calculate checksum of a blob, as it is defined by the ROM """
Tf0883e@staticmethod
Tff7b72def Td2a8ffchecksumTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3stateTff7b72=Te6edf3ESP_CHECKSUM_MAGICTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3b Tff7b72in Te6edf3dataTb4b4b4:
Tff7b72if Tffa657typeTb4b4b4(Te6edf3bTb4b4b4) Tff7b72is Tffa657intTb4b4b4: T8b949e# python 2/3 compat
Te6edf3state Tff7b72^Tff7b72= Te6edf3b
Tff7b72elseTb4b4b4:
Te6edf3state Tff7b72^Tff7b72= Tffa657ordTb4b4b4(Te6edf3bTb4b4b4)

Tff7b72return Te6edf3state

T8b949e""" Send a request and read the response """
Tff7b72def Td2a8ffcommandTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3opTff7b72=Tff7b72NoneTb4b4b4, Te6edf3dataTff7b72=Ta5d6ffbTa5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3chkTff7b72=T79c0ff0Tb4b4b4, Te6edf3wait_responseTff7b72=Tff7b72TrueTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3DEFAULT_TIMEOUTTb4b4b4)Tb4b4b4:
Te6edf3saved_timeout Tff7b72= Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8fftimeout
Te6edf3new_timeout Tff7b72= Tffa657minTb4b4b4(Te6edf3timeoutTb4b4b4, Te6edf3MAX_TIMEOUTTb4b4b4)
Tff7b72if Te6edf3new_timeout Tff7b72!= Te6edf3saved_timeoutTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8fftimeout Tff7b72= Te6edf3new_timeout

Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3op Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8fftraceTb4b4b4(Ta5d6ff"Ta5d6ffcommand op=0xTffd700%02xTa5d6ff data len=Tffd700%sTa5d6ff wait_response=Tffd700%dTa5d6ff timeout=Tffd700%.3fTa5d6ff data=Tffd700%sTa5d6ff"Tb4b4b4,
Te6edf3opTb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, T79c0ff1 Tff7b72if Te6edf3wait_response Tff7b72else T79c0ff0Tb4b4b4, Te6edf3timeoutTb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)
Te6edf3pkt Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ff<BBHITa5d6ff'Tb4b4b4, T79c0ff0x00Tb4b4b4, Te6edf3opTb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3chkTb4b4b4) Tff7b72+ Te6edf3data
Tff7b72selfTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3pktTb4b4b4)

Tff7b72if Tff7b72not Te6edf3wait_responseTb4b4b4:
Tff7b72return

T8b949e# tries to get a response until that response has the
T8b949e# same operation as the request or a retries limit has
T8b949e# exceeded. This is needed for some esp8266s that
T8b949e# reply with more sync responses than expected.
Tff7b72for Te6edf3retry Tff7b72in Tffa657rangeTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4:
Te6edf3p Tff7b72= Tff7b72selfTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3pTb4b4b4) Tff7b72< T79c0ff8Tb4b4b4:
Tff7b72continue
Tb4b4b4(Te6edf3respTb4b4b4, Te6edf3op_retTb4b4b4, Te6edf3len_retTb4b4b4, Te6edf3valTb4b4b4) Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff'Ta5d6ff<BBHITa5d6ff'Tb4b4b4, Te6edf3pTb4b4b4[Tb4b4b4:T79c0ff8Tb4b4b4]Tb4b4b4)
Tff7b72if Te6edf3resp Tff7b72!= T79c0ff1Tb4b4b4:
Tff7b72continue
Te6edf3data Tff7b72= Te6edf3pTb4b4b4[T79c0ff8Tb4b4b4:Tb4b4b4]

Tff7b72if Te6edf3op Tff7b72is Tff7b72None Tff7b72or Te6edf3op_ret Tff7b72== Te6edf3opTb4b4b4:
Tff7b72return Te6edf3valTb4b4b4, Te6edf3data
Tff7b72if Te6edf3byteTb4b4b4(Te6edf3dataTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72!= T79c0ff0 Tff7b72and Te6edf3byteTb4b4b4(Te6edf3dataTb4b4b4, T79c0ff1Tb4b4b4) Tff7b72== Tff7b72selfTff7b72.Td2a8ffROM_INVALID_RECV_MSGTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# Unsupported read_reg can result in more than one error response for some reason
Tff7b72raise Te6edf3UnsupportedCommandErrorTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3opTb4b4b4)

Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3new_timeout Tff7b72!= Te6edf3saved_timeoutTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8fftimeout Tff7b72= Te6edf3saved_timeout

Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffResponse doesnTa5d6ff'Ta5d6fft match requestTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffcheck_commandTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3op_descriptionTb4b4b4, Te6edf3opTff7b72=Tff7b72NoneTb4b4b4, Te6edf3dataTff7b72=Ta5d6ffbTa5d6ff'Ta5d6ff'Tb4b4b4, Te6edf3chkTff7b72=T79c0ff0Tb4b4b4, Te6edf3timeoutTff7b72=Te6edf3DEFAULT_TIMEOUTTb4b4b4)Tb4b4b4:
T8b949e"""
Execute a command with 'command', check the result code and throw an appropriate
FatalError if it fails.

Returns the "result" of a successful command.
"""
Te6edf3valTb4b4b4, Te6edf3data Tff7b72= Tff7b72selfTff7b72.Td2a8ffcommandTb4b4b4(Te6edf3opTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3chkTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

T8b949e# things are a bit weird here, bear with us

T8b949e# the status bytes are the last 2/4 bytes in the data (depending on chip)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< Tff7b72selfTff7b72.Td2a8ffSTATUS_BYTES_LENGTHTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffFailed to Tffd700%sTa5d6ff. Only got Tffd700%dTa5d6ff byte status response.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3op_descriptionTb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3status_bytes Tff7b72= Te6edf3dataTb4b4b4[Tff7b72-Tff7b72selfTff7b72.Td2a8ffSTATUS_BYTES_LENGTHTb4b4b4:Tb4b4b4]
T8b949e# we only care if the first one is non-zero. If it is, the second byte is a reason.
Tff7b72if Te6edf3byteTb4b4b4(Te6edf3status_bytesTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTff7b72.Td2a8ffWithResultTb4b4b4(Ta5d6ff'Ta5d6ffFailed to Tffd700%sTa5d6ff' Tff7b72% Te6edf3op_descriptionTb4b4b4, Te6edf3status_bytesTb4b4b4)

T8b949e# if we had more data than just the status bytes, return it as the result
T8b949e# (this is used by the md5sum command, maybe other commands?)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72> Tff7b72selfTff7b72.Td2a8ffSTATUS_BYTES_LENGTHTb4b4b4:
Tff7b72return Te6edf3dataTb4b4b4[Tb4b4b4:Tff7b72-Tff7b72selfTff7b72.Td2a8ffSTATUS_BYTES_LENGTHTb4b4b4]
Tff7b72elseTb4b4b4: T8b949e# otherwise, just return the 'val' field which comes from the reply header (this is used by read_reg)
Tff7b72return Te6edf3val

Tff7b72def Td2a8ffflush_inputTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffflushInputTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_slip_reader Tff7b72= Te6edf3slip_readerTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_portTb4b4b4, Tff7b72selfTff7b72.Td2a8fftraceTb4b4b4)

Tff7b72def Td2a8ffsyncTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3valTb4b4b4, Te6edf3_ Tff7b72= Tff7b72selfTff7b72.Td2a8ffcommandTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_SYNCTb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\x07Tffea00\x07Tffea00\x12Tffea00\x20Ta5d6ff' Tff7b72+ T79c0ff32 Tff7b72* Ta5d6ffbTa5d6ff'Tffea00\x55Ta5d6ff'Tb4b4b4,
Te6edf3timeoutTff7b72=Te6edf3SYNC_TIMEOUTTb4b4b4)

T8b949e# ROM bootloaders send some non-zero "val" response. The flasher stub sends 0. If we receive 0 then it
T8b949e# probably indicates that the chip wasn't or couldn't be reseted properly and esptool is talking to the
T8b949e# flasher stub.
Tff7b72selfTff7b72.Td2a8ffsync_stub_detected Tff7b72= Te6edf3val Tff7b72== T79c0ff0

Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(T79c0ff7Tb4b4b4)Tb4b4b4:
Te6edf3valTb4b4b4, Te6edf3_ Tff7b72= Tff7b72selfTff7b72.Td2a8ffcommandTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsync_stub_detected Tff7b72&Tff7b72= Te6edf3val Tff7b72== T79c0ff0

Tff7b72def Td2a8ff_setDTRTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3stateTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffsetDTRTb4b4b4(Te6edf3stateTb4b4b4)

Tff7b72def Td2a8ff_setRTSTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3stateTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffsetRTSTb4b4b4(Te6edf3stateTb4b4b4)
T8b949e# Work-around for adapters on Windows using the usbser.sys driver:
T8b949e# generate a dummy change to DTR so that the set-control-line-state
T8b949e# request is sent with the updated RTS state and the same DTR state
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffsetDTRTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffdtrTb4b4b4)

Tff7b72def Td2a8ff_get_pidTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3list_ports Tff7b72is Tff7b72NoneTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffListing all serial ports is currently not available. CanTa5d6ff'Ta5d6fft get device PID.Ta5d6ff"Tb4b4b4)
Tff7b72return
Te6edf3active_port Tff7b72= Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffport

T8b949e# Pyserial only identifies regular ports, URL handlers are not supported
Tff7b72if Tff7b72not Te6edf3active_portTff7b72.Td2a8ffstartswithTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffCOMTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/dev/Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffDevice PID identification is only supported on COM and /dev/ serial ports.Ta5d6ff"Tb4b4b4)
Tff7b72return
T8b949e# Return the real path if the active port is a symlink
Tff7b72if Te6edf3active_portTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ff/dev/Ta5d6ff"Tb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffislinkTb4b4b4(Te6edf3active_portTb4b4b4)Tb4b4b4:
Te6edf3active_port Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3active_portTb4b4b4)

Te6edf3ports Tff7b72= Te6edf3list_portsTff7b72.Td2a8ffcomportsTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3p Tff7b72in Te6edf3portsTb4b4b4:
Tff7b72if Te6edf3pTff7b72.Td2a8ffdevice Tff7b72== Te6edf3active_portTb4b4b4:
Tff7b72return Te6edf3pTff7b72.Td2a8ffpid
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffFailed to get PID of a device on Tffd700{}Ta5d6ff, using standard reset sequence.Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3active_portTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffbootloader_resetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3esp32r0_delayTff7b72=Tff7b72FalseTb4b4b4, Te6edf3usb_jtag_serialTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e""" Issue a reset-to-bootloader, with esp32r0 workaround options
and USB-JTAG-Serial custom reset sequence option
"""
T8b949e# RTS = either CH_PD/EN or nRESET (both active low = chip in reset)
T8b949e# DTR = GPIO0 (active low = boot to flasher)
T8b949e#
T8b949e# DTR & RTS are active low signals,
T8b949e# ie True = pin @ 0V, False = pin @ VCC.
Tff7b72if Te6edf3usb_jtag_serialTb4b4b4:
T8b949e# Custom reset sequence, which is required when the device
T8b949e# is connecting via its USB-JTAG-Serial peripheral
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72FalseTb4b4b4) T8b949e# Idle
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# Set IO0
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# Reset. Note dtr/rts calls inverted so we go through (1,1) instead of (0,0)
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# Extra RTS set for RTS as Windows only propagates DTR on RTS setting
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72FalseTb4b4b4) T8b949e# IO0=HIGH
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# EN=LOW, chip in reset
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
Tff7b72if Te6edf3esp32r0_delayTb4b4b4:
T8b949e# Some chips are more likely to trigger the esp32r0
T8b949e# watchdog reset silicon bug if they're held with EN=LOW
T8b949e# for a longer period
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff1.2Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# IO0=LOW
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4) T8b949e# EN=HIGH, chip out of reset
Tff7b72if Te6edf3esp32r0_delayTb4b4b4:
T8b949e# Sleep longer after reset.
T8b949e# This workaround only works on revision 0 ESP32 chips,
T8b949e# it exploits a silicon bug spurious watchdog reset.
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.4Tb4b4b4) T8b949e# allow watchdog reset to occur
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.05Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setDTRTb4b4b4(Tff7b72FalseTb4b4b4) T8b949e# IO0=HIGH, done

Tff7b72def Td2a8ff_connect_attemptTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3modeTff7b72=Ta5d6ff'Ta5d6ffdefault_resetTa5d6ff'Tb4b4b4, Te6edf3esp32r0_delayTff7b72=Tff7b72FalseTb4b4b4, Te6edf3usb_jtag_serialTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e""" A single connection attempt, with esp32r0 workaround options """
T8b949e# esp32r0_delay is a workaround for bugs with the most common auto reset
T8b949e# circuit and Windows, if the EN pin on the dev board does not have
T8b949e# enough capacitance.
T8b949e#
T8b949e# Newer dev boards shouldn't have this problem (higher value capacitor
T8b949e# on the EN pin), and ESP32 revision 1 can't use this workaround as it
T8b949e# relies on a silicon bug.
T8b949e#
T8b949e# Details: https://github.com/espressif/esptool/issues/136
Te6edf3last_error Tff7b72= Tff7b72None

T8b949e# If we're doing no_sync, we're likely communicating as a pass through
T8b949e# with an intermediate device to the ESP32
Tff7b72if Te6edf3mode Tff7b72== Ta5d6ff"Ta5d6ffno_reset_no_syncTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3last_error

Tff7b72if Te6edf3mode Tff7b72!= Ta5d6ff'Ta5d6ffno_resetTa5d6ff'Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbootloader_resetTb4b4b4(Te6edf3esp32r0_delayTb4b4b4, Te6edf3usb_jtag_serialTb4b4b4)

Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffflushOutputTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsyncTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72None
Tff7b72except Te6edf3FatalError Tff7b72as Te6edf3eTb4b4b4:
Tff7b72if Te6edf3esp32r0_delayTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff_Ta5d6ff'Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Ta5d6ff'Tb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff.Ta5d6ff'Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Ta5d6ff'Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.05Tb4b4b4)
Te6edf3last_error Tff7b72= Te6edf3e
Tff7b72return Te6edf3last_error

Tff7b72def Td2a8ffget_memory_regionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e""" Returns a tuple of (start, end) for the memory map entry with the given name, or None if it doesn't exist
"""
Tff7b72tryTb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4(Te6edf3startTb4b4b4, Te6edf3endTb4b4b4) Tff7b72for Tb4b4b4(Te6edf3startTb4b4b4, Te6edf3endTb4b4b4, Te6edf3nTb4b4b4) Tff7b72in Tff7b72selfTff7b72.Td2a8ffMEMORY_MAP Tff7b72if Te6edf3n Tff7b72== Te6edf3nameTb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72except Tf85149IndexErrorTb4b4b4:
Tff7b72return Tff7b72None

Tff7b72def Td2a8ffconnectTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3modeTff7b72=Ta5d6ff'Ta5d6ffdefault_resetTa5d6ff'Tb4b4b4, Te6edf3attemptsTff7b72=Te6edf3DEFAULT_CONNECT_ATTEMPTSTb4b4b4, Te6edf3detectingTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e""" Try connecting repeatedly until successful, or giving up """
Tff7b72if Te6edf3mode Tff7b72in Tb4b4b4[Ta5d6ff'Ta5d6ffno_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffno_reset_no_syncTa5d6ff'Tb4b4b4]Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: Pre-connection option Ta5d6ff"Tffd700{}Ta5d6ff"Ta5d6ff was selected.Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3modeTb4b4b4)Tb4b4b4,
Ta5d6ff'Ta5d6ffConnection may fail if the chip is not in bootloader or flasher stub mode.Ta5d6ff'Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffConnecting...Ta5d6ff'Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Ta5d6ff'Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3last_error Tff7b72= Tff7b72None

Te6edf3usb_jtag_serial Tff7b72= Tb4b4b4(Te6edf3mode Tff7b72== Ta5d6ff'Ta5d6ffusb_resetTa5d6ff'Tb4b4b4) Tff7b72or Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_get_pidTb4b4b4(Tb4b4b4) Tff7b72== Tff7b72selfTff7b72.Td2a8ffUSB_JTAG_SERIAL_PIDTb4b4b4)

Tff7b72tryTb4b4b4:
Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(Te6edf3attemptsTb4b4b4) Tff7b72if Te6edf3attempts Tff7b72> T79c0ff0 Tff7b72else Te6edf3itertoolsTff7b72.Td2a8ffcountTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3last_error Tff7b72= Tff7b72selfTff7b72.Td2a8ff_connect_attemptTb4b4b4(Te6edf3modeTff7b72=Te6edf3modeTb4b4b4, Te6edf3esp32r0_delayTff7b72=Tff7b72FalseTb4b4b4, Te6edf3usb_jtag_serialTff7b72=Te6edf3usb_jtag_serialTb4b4b4)
Tff7b72if Te6edf3last_error Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72break
Te6edf3last_error Tff7b72= Tff7b72selfTff7b72.Td2a8ff_connect_attemptTb4b4b4(Te6edf3modeTff7b72=Te6edf3modeTb4b4b4, Te6edf3esp32r0_delayTff7b72=Tff7b72TrueTb4b4b4, Te6edf3usb_jtag_serialTff7b72=Te6edf3usb_jtag_serialTb4b4b4)
Tff7b72if Te6edf3last_error Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72break
Tff7b72finallyTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff'Tb4b4b4) T8b949e# end 'Connecting...' line

Tff7b72if Te6edf3last_error Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffFailed to connect to Tffd700%sTa5d6ff: Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffCHIP_NAMETb4b4b4, Te6edf3last_errorTb4b4b4)Tb4b4b4)

Tff7b72if Tff7b72not Te6edf3detectingTb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# check the date code registers match what we expect to see
Te6edf3chip_magic_value Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffCHIP_DETECT_MAGIC_REG_ADDRTb4b4b4)
Tff7b72if Te6edf3chip_magic_value Tff7b72not Tff7b72in Tff7b72selfTff7b72.Td2a8ffCHIP_DETECT_MAGIC_VALUETb4b4b4:
Te6edf3actually Tff7b72= Tff7b72None
Tff7b72for Tff7b72cls Tff7b72in Tb4b4b4[Te6edf3ESP8266ROMTb4b4b4, Te6edf3ESP32ROMTb4b4b4, Te6edf3ESP32S2ROMTb4b4b4, Te6edf3ESP32S3BETA2ROMTb4b4b4, Te6edf3ESP32S3BETA3ROMTb4b4b4, Te6edf3ESP32C3ROMTb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3chip_magic_value Tff7b72in Tff7b72clsTff7b72.Td2a8ffCHIP_DETECT_MAGIC_VALUETb4b4b4:
Te6edf3actually Tff7b72= Tff7b72cls
Tff7b72break
Tff7b72if Te6edf3actually Tff7b72is Tff7b72NoneTb4b4b4:
Tffa657printTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffWARNING: This chip doesnTa5d6ff'Ta5d6fft appear to be a Tffd700%sTa5d6ff (chip magic value 0xTffd700%08xTa5d6ff). Ta5d6ff"
Ta5d6ff"Ta5d6ffProbably it is unsupported by this version of esptool.Ta5d6ff"Tb4b4b4) Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffCHIP_NAMETb4b4b4, Te6edf3chip_magic_valueTb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffThis chip is Tffd700%sTa5d6ff not Tffd700%sTa5d6ff. Wrong --chip argument?Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3actuallyTff7b72.Td2a8ffCHIP_NAMETb4b4b4, Tff7b72selfTff7b72.Td2a8ffCHIP_NAMETb4b4b4)Tb4b4b4)
Tff7b72except Te6edf3UnsupportedCommandErrorTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ff_post_connectTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ff_post_connectTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
Additional initialization hook, may be overridden by the chip-specific class.
Gets called after connect, and after auto-detection.
"""
Tff7b72pass

Tff7b72def Td2a8ffread_regTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3DEFAULT_TIMEOUTTb4b4b4)Tb4b4b4:
T8b949e""" Read memory address in target """
T8b949e# we don't call check_command here because read_reg() function is called
T8b949e# when detecting chip type, and the way we check for success (STATUS_BYTES_LENGTH) is different
T8b949e# for different chip types (!)
Te6edf3valTb4b4b4, Te6edf3data Tff7b72= Tff7b72selfTff7b72.Td2a8ffcommandTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_READ_REGTb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Te6edf3addrTb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72if Te6edf3byteTb4b4b4(Te6edf3dataTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTff7b72.Td2a8ffWithResultTb4b4b4(Ta5d6ff"Ta5d6ffFailed to read register address Tffd700%08xTa5d6ff" Tff7b72% Te6edf3addrTb4b4b4, Te6edf3dataTb4b4b4)
Tff7b72return Te6edf3val

T8b949e""" Write to memory address in target """
Tff7b72def Td2a8ffwrite_regTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3valueTb4b4b4, Te6edf3maskTff7b72=T79c0ff0xFFFFFFFFTb4b4b4, Te6edf3delay_usTff7b72=T79c0ff0Tb4b4b4, Te6edf3delay_after_usTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4:
Te6edf3command Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Te6edf3addrTb4b4b4, Te6edf3valueTb4b4b4, Te6edf3maskTb4b4b4, Te6edf3delay_usTb4b4b4)
Tff7b72if Te6edf3delay_after_us Tff7b72> T79c0ff0Tb4b4b4:
T8b949e# add a dummy write to a date register as an excuse to have a delay
Te6edf3command Tff7b72+Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffUART_DATE_REG_ADDRTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3delay_after_usTb4b4b4)

Tff7b72return Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffwrite target memoryTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_WRITE_REGTb4b4b4, Te6edf3commandTb4b4b4)

Tff7b72def Td2a8ffupdate_regTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3maskTb4b4b4, Te6edf3new_valTb4b4b4)Tb4b4b4:
T8b949e""" Update register at 'addr', replace the bits masked out by 'mask'
with new_val. new_val is shifted left to match the LSB of 'mask'

Returns just-written value of register.
"""
Te6edf3shift Tff7b72= Te6edf3_mask_to_shiftTb4b4b4(Te6edf3maskTb4b4b4)
Te6edf3val Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3addrTb4b4b4)
Te6edf3val Tff7b72&Tff7b72= Tff7b72~Te6edf3mask
Te6edf3val Tff7b72|Tff7b72= Tb4b4b4(Te6edf3new_val Tff7b72<< Te6edf3shiftTb4b4b4) Tff7b72& Te6edf3mask
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3addrTb4b4b4, Te6edf3valTb4b4b4)

Tff7b72return Te6edf3val

T8b949e""" Start downloading an application image to RAM """
Tff7b72def Td2a8ffmem_beginTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3blocksTb4b4b4, Te6edf3blocksizeTb4b4b4, Te6edf3offsetTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4: T8b949e# check we're not going to overwrite a running stub with this data
Te6edf3stub Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTUB_CODE
Te6edf3load_start Tff7b72= Te6edf3offset
Te6edf3load_end Tff7b72= Te6edf3offset Tff7b72+ Te6edf3size
Tff7b72for Tb4b4b4(Te6edf3startTb4b4b4, Te6edf3endTb4b4b4) Tff7b72in Tb4b4b4[Tb4b4b4(Te6edf3stubTb4b4b4[Ta5d6ff"Ta5d6ffdata_startTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3stubTb4b4b4[Ta5d6ff"Ta5d6ffdata_startTa5d6ff"Tb4b4b4] Tff7b72+ Tffa657lenTb4b4b4(Te6edf3stubTb4b4b4[Ta5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4(Te6edf3stubTb4b4b4[Ta5d6ff"Ta5d6fftext_startTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3stubTb4b4b4[Ta5d6ff"Ta5d6fftext_startTa5d6ff"Tb4b4b4] Tff7b72+ Tffa657lenTb4b4b4(Te6edf3stubTb4b4b4[Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3load_start Tff7b72< Te6edf3end Tff7b72and Te6edf3load_end Tff7b72> Te6edf3startTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffSoftware loader is resident at 0xTffd700%08xTa5d6ff-0xTffd700%08xTa5d6ff. Ta5d6ff"
Ta5d6ff"Ta5d6ffCanTa5d6ff'Ta5d6fft load binary at overlapping address range 0xTffd700%08xTa5d6ff-0xTffd700%08xTa5d6ff. Ta5d6ff"
Ta5d6ff"Ta5d6ffEither change binary loading address, or use the --no-stub Ta5d6ff"
Ta5d6ff"Ta5d6ffoption to disable the software loader.Ta5d6ff"Tb4b4b4) Tff7b72% Tb4b4b4(Te6edf3startTb4b4b4, Te6edf3endTb4b4b4, Te6edf3load_startTb4b4b4, Te6edf3load_endTb4b4b4)Tb4b4b4)

Tff7b72return Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffenter RAM download modeTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_MEM_BEGINTb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3blocksTb4b4b4, Te6edf3blocksizeTb4b4b4, Te6edf3offsetTb4b4b4)Tb4b4b4)

T8b949e""" Send a block of an image to RAM """
Tff7b72def Td2a8ffmem_blockTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3seqTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffwrite to target RAMTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_MEM_DATATb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3seqTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72+ Te6edf3dataTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffchecksumTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)

T8b949e""" Leave download mode and run the application """
Tff7b72def Td2a8ffmem_finishTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3entrypointTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4:
T8b949e# Sending ESP_MEM_END usually sends a correct response back, however sometimes
T8b949e# (with ROM loader) the executed code may reset the UART or change the baud rate
T8b949e# before the transmit FIFO is empty. So in these cases we set a short timeout and
T8b949e# ignore errors.
Te6edf3timeout Tff7b72= Te6edf3DEFAULT_TIMEOUT Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUB Tff7b72else Te6edf3MEM_END_ROM_TIMEOUT
Te6edf3data Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IITa5d6ff'Tb4b4b4, Tffa657intTb4b4b4(Te6edf3entrypoint Tff7b72== T79c0ff0Tb4b4b4)Tb4b4b4, Te6edf3entrypointTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffleave RAM download modeTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_MEM_ENDTb4b4b4,
Te6edf3dataTff7b72=Te6edf3dataTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72except Te6edf3FatalErrorTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Tff7b72raise
Tff7b72pass

T8b949e""" Start downloading to Flash (performs an erase)

Returns number of blocks (of size self.FLASH_WRITE_SIZE) to write.
"""
Tff7b72def Td2a8ffflash_beginTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3begin_rom_encryptedTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3num_blocks Tff7b72= Tb4b4b4(Te6edf3size Tff7b72+ Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE Tff7b72- T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE
Te6edf3erase_size Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_erase_sizeTb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)

Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3timeout Tff7b72= Te6edf3DEFAULT_TIMEOUT
Tff7b72elseTb4b4b4:
Te6edf3timeout Tff7b72= Te6edf3timeout_per_mbTb4b4b4(Te6edf3ERASE_REGION_TIMEOUT_PER_MBTb4b4b4, Te6edf3sizeTb4b4b4) T8b949e# ROM performs the erase up front

Te6edf3params Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Te6edf3erase_sizeTb4b4b4, Te6edf3num_blocksTb4b4b4, Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZETb4b4b4, Te6edf3offsetTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Tff7b72selfTb4b4b4, Tb4b4b4(Te6edf3ESP32S2ROMTb4b4b4, Te6edf3ESP32S3BETA2ROMTb4b4b4, Te6edf3ESP32S3BETA3ROMTb4b4b4, Te6edf3ESP32C3ROMTb4b4b4, Te6edf3ESP32C6BETAROMTb4b4b4)Tb4b4b4) Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3params Tff7b72+Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, T79c0ff1 Tff7b72if Te6edf3begin_rom_encrypted Tff7b72else T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffenter Flash download modeTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_FLASH_BEGINTb4b4b4,
Te6edf3paramsTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72if Te6edf3size Tff7b72!= T79c0ff0 Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffTook Tffd700%.2fTa5d6ffs to erase flash blockTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3tTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3num_blocks

T8b949e""" Write block to flash """
Tff7b72def Td2a8ffflash_blockTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3seqTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3DEFAULT_TIMEOUTTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffwrite to target Flash after seq Tffd700%dTa5d6ff" Tff7b72% Te6edf3seqTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffESP_FLASH_DATATb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3seqTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72+ Te6edf3dataTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffchecksumTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4,
Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

T8b949e""" Encrypt before writing to flash """
Tff7b72def Td2a8ffflash_encrypt_blockTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3seqTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3DEFAULT_TIMEOUTTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Tff7b72selfTb4b4b4, Tb4b4b4(Te6edf3ESP32S2ROMTb4b4b4, Te6edf3ESP32C3ROMTb4b4b4)Tb4b4b4) Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
T8b949e# ROM support performs the encrypted writes via the normal write command,
T8b949e# triggered by flash_begin(begin_rom_encrypted=True)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffflash_blockTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3seqTb4b4b4, Te6edf3timeoutTb4b4b4)

Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffWrite encrypted to target Flash after seq Tffd700%dTa5d6ff" Tff7b72% Te6edf3seqTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffESP_FLASH_ENCRYPT_DATATb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3seqTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72+ Te6edf3dataTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffchecksumTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4,
Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

T8b949e""" Leave flash mode and run/reboot """
Tff7b72def Td2a8ffflash_finishTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rebootTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3pkt Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Tffa657intTb4b4b4(Tff7b72not Te6edf3rebootTb4b4b4)Tb4b4b4)
T8b949e# stub sends a reply to this command
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffleave Flash modeTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_FLASH_ENDTb4b4b4, Te6edf3pktTb4b4b4)

T8b949e""" Run application code in flash """
Tff7b72def Td2a8ffrunTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rebootTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e# Fake flash begin immediately followed by flash end
Tff7b72selfTff7b72.Td2a8ffflash_beginTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffflash_finishTb4b4b4(Te6edf3rebootTb4b4b4)

T8b949e""" Read SPI flash manufacturer and device id """
Tff7b72def Td2a8ffflash_idTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3SPIFLASH_RDID Tff7b72= T79c0ff0x9F
Tff7b72return Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3SPIFLASH_RDIDTb4b4b4, Ta5d6ffbTa5d6ff"Ta5d6ff"Tb4b4b4, T79c0ff24Tb4b4b4)

Tff7b72def Td2a8ffget_security_infoTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# TODO: this only works on the ESP32S2 ROM code loader and needs to work in stub loader also
Te6edf3res Tff7b72= Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff'Ta5d6ffget security infoTa5d6ff'Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_GET_SECURITY_INFOTb4b4b4, Ta5d6ffbTa5d6ff'Ta5d6ff'Tb4b4b4)
Te6edf3res Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff<IBBBBBBBBTa5d6ff"Tb4b4b4, Te6edf3resTb4b4b4)
Te6edf3flagsTb4b4b4, Te6edf3flash_crypt_cntTb4b4b4, Te6edf3key_purposes Tff7b72= Te6edf3resTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3resTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4, Te6edf3resTb4b4b4[T79c0ff2Tb4b4b4:Tb4b4b4]
T8b949e# TODO: pack this as some kind of better data type
Tff7b72return Tb4b4b4(Te6edf3flagsTb4b4b4, Te6edf3flash_crypt_cntTb4b4b4, Te6edf3key_purposesTb4b4b4)

Tf0883e@classmethod
Tff7b72def Td2a8ffparse_flash_size_argTb4b4b4(Tff7b72clsTb4b4b4, Te6edf3argTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72return Tff7b72clsTff7b72.Td2a8ffFLASH_SIZESTb4b4b4[Te6edf3argTb4b4b4]
Tff7b72except Tf85149KeyErrorTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffFlash size Ta5d6ff'Tffd700%sTa5d6ff'Ta5d6ff is not supported by this chip type. Supported sizes: Tffd700%sTa5d6ff"
Tff7b72% Tb4b4b4(Te6edf3argTb4b4b4, Ta5d6ff"Ta5d6ff, Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Tff7b72clsTff7b72.Td2a8ffFLASH_SIZESTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffrun_stubTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3stubTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3stub Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3stub Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTUB_CODE

Tff7b72if Tff7b72selfTff7b72.Td2a8ffsync_stub_detectedTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffStub is already running. No upload is necessary.Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffSTUB_CLASSTb4b4b4(Tff7b72selfTb4b4b4)

T8b949e# Upload
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffUploading stub...Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3field Tff7b72in Tb4b4b4[Ta5d6ff'Ta5d6fftextTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffdataTa5d6ff'Tb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3field Tff7b72in Te6edf3stubTb4b4b4:
Te6edf3offs Tff7b72= Te6edf3stubTb4b4b4[Te6edf3field Tff7b72+ Ta5d6ff"Ta5d6ff_startTa5d6ff"Tb4b4b4]
Te6edf3length Tff7b72= Tffa657lenTb4b4b4(Te6edf3stubTb4b4b4[Te6edf3fieldTb4b4b4]Tb4b4b4)
Te6edf3blocks Tff7b72= Tb4b4b4(Te6edf3length Tff7b72+ Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCK Tff7b72- T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCK
Tff7b72selfTff7b72.Td2a8ffmem_beginTb4b4b4(Te6edf3lengthTb4b4b4, Te6edf3blocksTb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCKTb4b4b4, Te6edf3offsTb4b4b4)
Tff7b72for Te6edf3seq Tff7b72in Tffa657rangeTb4b4b4(Te6edf3blocksTb4b4b4)Tb4b4b4:
Te6edf3from_offs Tff7b72= Te6edf3seq Tff7b72* Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCK
Te6edf3to_offs Tff7b72= Te6edf3from_offs Tff7b72+ Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCK
Tff7b72selfTff7b72.Td2a8ffmem_blockTb4b4b4(Te6edf3stubTb4b4b4[Te6edf3fieldTb4b4b4]Tb4b4b4[Te6edf3from_offsTb4b4b4:Te6edf3to_offsTb4b4b4]Tb4b4b4, Te6edf3seqTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffRunning stub...Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmem_finishTb4b4b4(Te6edf3stubTb4b4b4[Ta5d6ff'Ta5d6ffentryTa5d6ff'Tb4b4b4]Tb4b4b4)

Te6edf3p Tff7b72= Tff7b72selfTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3p Tff7b72!= Ta5d6ffbTa5d6ff'Ta5d6ffOHAITa5d6ff'Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffFailed to start stub. Unexpected response: Tffd700%sTa5d6ff" Tff7b72% Te6edf3pTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffStub running...Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffSTUB_CLASSTb4b4b4(Tff7b72selfTb4b4b4)

Tf0883e@stub_and_esp32_function_only
Tff7b72def Td2a8ffflash_defl_beginTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3compsizeTb4b4b4, Te6edf3offsetTb4b4b4)Tb4b4b4:
T8b949e""" Start downloading compressed data to Flash (performs an erase)

Returns number of blocks (size self.FLASH_WRITE_SIZE) to write.
"""
Te6edf3num_blocks Tff7b72= Tb4b4b4(Te6edf3compsize Tff7b72+ Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE Tff7b72- T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE
Te6edf3erase_blocks Tff7b72= Tb4b4b4(Te6edf3size Tff7b72+ Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE Tff7b72- T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE

Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3write_size Tff7b72= Te6edf3size T8b949e# stub expects number of bytes here, manages erasing internally
Te6edf3timeout Tff7b72= Te6edf3DEFAULT_TIMEOUT
Tff7b72elseTb4b4b4:
Te6edf3write_size Tff7b72= Te6edf3erase_blocks Tff7b72* Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE T8b949e# ROM expects rounded up to erase block size
Te6edf3timeout Tff7b72= Te6edf3timeout_per_mbTb4b4b4(Te6edf3ERASE_REGION_TIMEOUT_PER_MBTb4b4b4, Te6edf3write_sizeTb4b4b4) T8b949e# ROM performs the erase up front
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffCompressed Tffd700%dTa5d6ff bytes to Tffd700%dTa5d6ff...Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3compsizeTb4b4b4)Tb4b4b4)
Te6edf3params Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Te6edf3write_sizeTb4b4b4, Te6edf3num_blocksTb4b4b4, Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZETb4b4b4, Te6edf3offsetTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Tff7b72selfTb4b4b4, Tb4b4b4(Te6edf3ESP32S2ROMTb4b4b4, Te6edf3ESP32S3BETA2ROMTb4b4b4, Te6edf3ESP32S3BETA3ROMTb4b4b4, Te6edf3ESP32C3ROMTb4b4b4, Te6edf3ESP32C6BETAROMTb4b4b4)Tb4b4b4) Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3params Tff7b72+Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, T79c0ff0Tb4b4b4) T8b949e# extra param is to enter encrypted flash mode via ROM (not supported currently)
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffenter compressed flash modeTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_FLASH_DEFL_BEGINTb4b4b4, Te6edf3paramsTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72if Te6edf3size Tff7b72!= T79c0ff0 Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
T8b949e# (stub erases as it writes, but ROM loaders erase on begin)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffTook Tffd700%.2fTa5d6ffs to erase flash blockTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3tTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3num_blocks

T8b949e""" Write block to flash, send compressed """
Tf0883e@stub_and_esp32_function_only
Tff7b72def Td2a8ffflash_defl_blockTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3seqTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3DEFAULT_TIMEOUTTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffwrite compressed data to flash after seq Tffd700%dTa5d6ff" Tff7b72% Te6edf3seqTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffESP_FLASH_DEFL_DATATb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3seqTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72+ Te6edf3dataTb4b4b4, Tff7b72selfTff7b72.Td2a8ffchecksumTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

T8b949e""" Leave compressed flash mode and run/reboot """
Tf0883e@stub_and_esp32_function_only
Tff7b72def Td2a8ffflash_defl_finishTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rebootTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3reboot Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
T8b949e# skip sending flash_finish to ROM loader, as this
T8b949e# exits the bootloader. Stub doesn't do this.
Tff7b72return
Te6edf3pkt Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Tffa657intTb4b4b4(Tff7b72not Te6edf3rebootTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffleave compressed flash modeTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_FLASH_DEFL_ENDTb4b4b4, Te6edf3pktTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffin_bootloader Tff7b72= Tff7b72False

Tf0883e@stub_and_esp32_function_only
Tff7b72def Td2a8ffflash_md5sumTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
T8b949e# the MD5 command returns additional bytes in the standard
T8b949e# command reply slot
Te6edf3timeout Tff7b72= Te6edf3timeout_per_mbTb4b4b4(Te6edf3MD5_TIMEOUT_PER_MBTb4b4b4, Te6edf3sizeTb4b4b4)
Te6edf3res Tff7b72= Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff'Ta5d6ffcalculate md5sumTa5d6ff'Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_SPI_FLASH_MD5Tb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4, Te6edf3addrTb4b4b4, Te6edf3sizeTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4,
Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

Tff7b72if Tffa657lenTb4b4b4(Te6edf3resTb4b4b4) Tff7b72== T79c0ff32Tb4b4b4:
Tff7b72return Te6edf3resTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) T8b949e# already hex formatted
Tff7b72elif Tffa657lenTb4b4b4(Te6edf3resTb4b4b4) Tff7b72== T79c0ff16Tb4b4b4:
Tff7b72return Te6edf3hexifyTb4b4b4(Te6edf3resTb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffMD5Sum command returned unexpected result: Tffd700%rTa5d6ff" Tff7b72% Te6edf3resTb4b4b4)

Tf0883e@stub_and_esp32_function_only
Tff7b72def Td2a8ffchange_baudTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3baudTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffChanging baud rate to Tffd700%dTa5d6ff" Tff7b72% Te6edf3baudTb4b4b4)
T8b949e# stub takes the new baud rate and the old one
Te6edf3second_arg Tff7b72= Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffbaudrate Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUB Tff7b72else T79c0ff0
Tff7b72selfTff7b72.Td2a8ffcommandTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_CHANGE_BAUDRATETb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IITa5d6ff'Tb4b4b4, Te6edf3baudTb4b4b4, Te6edf3second_argTb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffChanged.Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_set_port_baudrateTb4b4b4(Te6edf3baudTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.05Tb4b4b4) T8b949e# get rid of crap sent during baud rate change
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4)

Tf0883e@stub_function_only
Tff7b72def Td2a8fferase_flashTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# depending on flash chip model the erase may take this long (maybe longer!)
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6fferase flashTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_ERASE_FLASHTb4b4b4,
Te6edf3timeoutTff7b72=Te6edf3CHIP_ERASE_TIMEOUTTb4b4b4)

Tf0883e@stub_function_only
Tff7b72def Td2a8fferase_regionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3offset Tff7b72% Tff7b72selfTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffOffset to erase from must be a multiple of 4096Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3size Tff7b72% Tff7b72selfTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffSize of data to erase must be a multiple of 4096Ta5d6ff"Tb4b4b4)
Te6edf3timeout Tff7b72= Te6edf3timeout_per_mbTb4b4b4(Te6edf3ERASE_REGION_TIMEOUT_PER_MBTb4b4b4, Te6edf3sizeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6fferase regionTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_ERASE_REGIONTb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IITa5d6ff'Tb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

Tff7b72def Td2a8ffread_flash_slowTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3lengthTb4b4b4, Te6edf3progress_fnTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3NotImplementedInROMErrorTb4b4b4(Tff7b72selfTb4b4b4, Tff7b72selfTff7b72.Td2a8ffread_flash_slowTb4b4b4)

Tff7b72def Td2a8ffread_flashTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3lengthTb4b4b4, Te6edf3progress_fnTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffread_flash_slowTb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3lengthTb4b4b4, Te6edf3progress_fnTb4b4b4) T8b949e# ROM-only routine

T8b949e# issue a standard bootloader command to trigger the read
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffread flashTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_READ_FLASHTb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIITa5d6ff'Tb4b4b4,
Te6edf3offsetTb4b4b4,
Te6edf3lengthTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffFLASH_SECTOR_SIZETb4b4b4,
T79c0ff64Tb4b4b4)Tb4b4b4)
T8b949e# now we expect (length // block_size) SLIP frames with the data
Te6edf3data Tff7b72= Ta5d6ffbTa5d6ff'Ta5d6ff'
Tff7b72while Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< Te6edf3lengthTb4b4b4:
Te6edf3p Tff7b72= Tff7b72selfTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Te6edf3data Tff7b72+Tff7b72= Te6edf3p
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< Te6edf3length Tff7b72and Tffa657lenTb4b4b4(Te6edf3pTb4b4b4) Tff7b72< Tff7b72selfTff7b72.Td2a8ffFLASH_SECTOR_SIZETb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffCorrupt data, expected 0xTffd700%xTa5d6ff bytes but received 0xTffd700%xTa5d6ff bytesTa5d6ff' Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffFLASH_SECTOR_SIZETb4b4b4, Tffa657lenTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3progress_fn Tff7b72and Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72% T79c0ff1024 Tff7b72== T79c0ff0 Tff7b72or Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72== Te6edf3lengthTb4b4b4)Tb4b4b4:
Te6edf3progress_fnTb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3lengthTb4b4b4)
Tff7b72if Te6edf3progress_fnTb4b4b4:
Te6edf3progress_fnTb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3lengthTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72> Te6edf3lengthTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffRead more than expectedTa5d6ff'Tb4b4b4)

Te6edf3digest_frame Tff7b72= Tff7b72selfTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3digest_frameTb4b4b4) Tff7b72!= T79c0ff16Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffExpected digest, got: Tffd700%sTa5d6ff' Tff7b72% Te6edf3hexifyTb4b4b4(Te6edf3digest_frameTb4b4b4)Tb4b4b4)
Te6edf3expected_digest Tff7b72= Te6edf3hexifyTb4b4b4(Te6edf3digest_frameTb4b4b4)Tff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)
Te6edf3digest Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffmd5Tb4b4b4(Te6edf3dataTb4b4b4)Tff7b72.Td2a8ffhexdigestTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3digest Tff7b72!= Te6edf3expected_digestTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffDigest mismatch: expected Tffd700%sTa5d6ff, got Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3expected_digestTb4b4b4, Te6edf3digestTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3data

Tff7b72def Td2a8ffflash_spi_attachTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3hspi_argTb4b4b4)Tb4b4b4:
T8b949e"""Send SPI attach command to enable the SPI flash pins

ESP8266 ROM does this when you send flash_begin, ESP32 ROM
has it as a SPI command.
"""
T8b949e# last 3 bytes in ESP_SPI_ATTACH argument are reserved values
Te6edf3arg Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Te6edf3hspi_argTb4b4b4)
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
T8b949e# ESP32 ROM loader takes additional 'is legacy' arg, which is not
T8b949e# currently supported in the stub loader or esptool.py (as it's not usually needed.)
Te6edf3is_legacy Tff7b72= T79c0ff0
Te6edf3arg Tff7b72+Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ffBBBBTa5d6ff'Tb4b4b4, Te6edf3is_legacyTb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffconfigure SPI flash pinsTa5d6ff"Tb4b4b4, Te6edf3ESP32ROMTff7b72.Td2a8ffESP_SPI_ATTACHTb4b4b4, Te6edf3argTb4b4b4)

Tff7b72def Td2a8ffflash_set_parametersTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
T8b949e"""Tell the ESP bootloader the parameters of the chip

Corresponds to the "flashchip" data structure that the ROM
has in RAM.

'size' is in bytes.

All other flash parameters are currently hardcoded (on ESP8266
these are mostly ignored by ROM code, on ESP32 I'm not sure.)
"""
Te6edf3fl_id Tff7b72= T79c0ff0
Te6edf3total_size Tff7b72= Te6edf3size
Te6edf3block_size Tff7b72= T79c0ff64 Tff7b72* T79c0ff1024
Te6edf3sector_size Tff7b72= T79c0ff4 Tff7b72* T79c0ff1024
Te6edf3page_size Tff7b72= T79c0ff256
Te6edf3status_mask Tff7b72= T79c0ff0xffff
Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffset SPI paramsTa5d6ff"Tb4b4b4, Te6edf3ESP32ROMTff7b72.Td2a8ffESP_SPI_SET_PARAMSTb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IIIIIITa5d6ff'Tb4b4b4, Te6edf3fl_idTb4b4b4, Te6edf3total_sizeTb4b4b4, Te6edf3block_sizeTb4b4b4, Te6edf3sector_sizeTb4b4b4, Te6edf3page_sizeTb4b4b4, Te6edf3status_maskTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffrun_spiflash_commandTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3spiflash_commandTb4b4b4, Te6edf3dataTff7b72=Ta5d6ffbTa5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3read_bitsTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4:
T8b949e"""Run an arbitrary SPI flash command.

This function uses the "USR_COMMAND" functionality in the ESP
SPI hardware, rather than the precanned commands supported by
hardware. So the value of spiflash_command is an actual command
byte, sent over the wire.

After writing command byte, writes 'data' to MOSI and then
reads back 'read_bits' of reply on MISO. Result is a number.
"""

T8b949e# SPI_USR register flags
Te6edf3SPI_USR_COMMAND Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff31Tb4b4b4)
Te6edf3SPI_USR_MISO Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff28Tb4b4b4)
Te6edf3SPI_USR_MOSI Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff27Tb4b4b4)

T8b949e# SPI registers, base address differs ESP32* vs 8266
Te6edf3base Tff7b72= Tff7b72selfTff7b72.Td2a8ffSPI_REG_BASE
Te6edf3SPI_CMD_REG Tff7b72= Te6edf3base Tff7b72+ T79c0ff0x00
Te6edf3SPI_USR_REG Tff7b72= Te6edf3base Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSPI_USR_OFFS
Te6edf3SPI_USR1_REG Tff7b72= Te6edf3base Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSPI_USR1_OFFS
Te6edf3SPI_USR2_REG Tff7b72= Te6edf3base Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSPI_USR2_OFFS
Te6edf3SPI_W0_REG Tff7b72= Te6edf3base Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSPI_W0_OFFS

T8b949e# following two registers are ESP32 & 32S2/32C3 only
Tff7b72if Tff7b72selfTff7b72.Td2a8ffSPI_MOSI_DLEN_OFFS Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
T8b949e# ESP32/32S2/32C3 has a more sophisticated way to set up "user" commands
Tff7b72def Td2a8ffset_data_lengthsTb4b4b4(Te6edf3mosi_bitsTb4b4b4, Te6edf3miso_bitsTb4b4b4)Tb4b4b4:
Te6edf3SPI_MOSI_DLEN_REG Tff7b72= Te6edf3base Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSPI_MOSI_DLEN_OFFS
Te6edf3SPI_MISO_DLEN_REG Tff7b72= Te6edf3base Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSPI_MISO_DLEN_OFFS
Tff7b72if Te6edf3mosi_bits Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_MOSI_DLEN_REGTb4b4b4, Te6edf3mosi_bits Tff7b72- T79c0ff1Tb4b4b4)
Tff7b72if Te6edf3miso_bits Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_MISO_DLEN_REGTb4b4b4, Te6edf3miso_bits Tff7b72- T79c0ff1Tb4b4b4)
Tff7b72elseTb4b4b4:

Tff7b72def Td2a8ffset_data_lengthsTb4b4b4(Te6edf3mosi_bitsTb4b4b4, Te6edf3miso_bitsTb4b4b4)Tb4b4b4:
Te6edf3SPI_DATA_LEN_REG Tff7b72= Te6edf3SPI_USR1_REG
Te6edf3SPI_MOSI_BITLEN_S Tff7b72= T79c0ff17
Te6edf3SPI_MISO_BITLEN_S Tff7b72= T79c0ff8
Te6edf3mosi_mask Tff7b72= T79c0ff0 Tff7b72if Tb4b4b4(Te6edf3mosi_bits Tff7b72== T79c0ff0Tb4b4b4) Tff7b72else Tb4b4b4(Te6edf3mosi_bits Tff7b72- T79c0ff1Tb4b4b4)
Te6edf3miso_mask Tff7b72= T79c0ff0 Tff7b72if Tb4b4b4(Te6edf3miso_bits Tff7b72== T79c0ff0Tb4b4b4) Tff7b72else Tb4b4b4(Te6edf3miso_bits Tff7b72- T79c0ff1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_DATA_LEN_REGTb4b4b4,
Tb4b4b4(Te6edf3miso_mask Tff7b72<< Te6edf3SPI_MISO_BITLEN_STb4b4b4) Tff7b72| Tb4b4b4(
Te6edf3mosi_mask Tff7b72<< Te6edf3SPI_MOSI_BITLEN_STb4b4b4)Tb4b4b4)

T8b949e# SPI peripheral "command" bitmasks for SPI_CMD_REG
Te6edf3SPI_CMD_USR Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff18Tb4b4b4)

T8b949e# shift values
Te6edf3SPI_USR2_COMMAND_LEN_SHIFT Tff7b72= T79c0ff28

Tff7b72if Te6edf3read_bits Tff7b72> T79c0ff32Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffReading more than 32 bits back from a SPI flash operation is unsupportedTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72> T79c0ff64Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffWriting more than 64 bytes of data with one SPI command is unsupportedTa5d6ff"Tb4b4b4)

Te6edf3data_bits Tff7b72= Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72* T79c0ff8
Te6edf3old_spi_usr Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3SPI_USR_REGTb4b4b4)
Te6edf3old_spi_usr2 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3SPI_USR2_REGTb4b4b4)
Te6edf3flags Tff7b72= Te6edf3SPI_USR_COMMAND
Tff7b72if Te6edf3read_bits Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3flags Tff7b72|Tff7b72= Te6edf3SPI_USR_MISO
Tff7b72if Te6edf3data_bits Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3flags Tff7b72|Tff7b72= Te6edf3SPI_USR_MOSI
Te6edf3set_data_lengthsTb4b4b4(Te6edf3data_bitsTb4b4b4, Te6edf3read_bitsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_USR_REGTb4b4b4, Te6edf3flagsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_USR2_REGTb4b4b4,
Tb4b4b4(T79c0ff7 Tff7b72<< Te6edf3SPI_USR2_COMMAND_LEN_SHIFTTb4b4b4) Tff7b72| Te6edf3spiflash_commandTb4b4b4)
Tff7b72if Te6edf3data_bits Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_W0_REGTb4b4b4, T79c0ff0Tb4b4b4) T8b949e# clear data register before we read it
Tff7b72elseTb4b4b4:
Te6edf3data Tff7b72= Te6edf3pad_toTb4b4b4(Te6edf3dataTb4b4b4, T79c0ff4Tb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\00Ta5d6ff'Tb4b4b4) T8b949e# pad to 32-bit multiple
Te6edf3words Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ffITa5d6ff" Tff7b72* Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72/Tff7b72/ T79c0ff4Tb4b4b4)Tb4b4b4, Te6edf3dataTb4b4b4)
Te6edf3next_reg Tff7b72= Te6edf3SPI_W0_REG
Tff7b72for Te6edf3word Tff7b72in Te6edf3wordsTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3next_regTb4b4b4, Te6edf3wordTb4b4b4)
Te6edf3next_reg Tff7b72+Tff7b72= T79c0ff4
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_CMD_REGTb4b4b4, Te6edf3SPI_CMD_USRTb4b4b4)

Tff7b72def Td2a8ffwait_doneTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(T79c0ff10Tb4b4b4)Tb4b4b4:
Tff7b72if Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3SPI_CMD_REGTb4b4b4) Tff7b72& Te6edf3SPI_CMD_USRTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72return
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffSPI command did not complete in timeTa5d6ff"Tb4b4b4)
Te6edf3wait_doneTb4b4b4(Tb4b4b4)

Te6edf3status Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3SPI_W0_REGTb4b4b4)
T8b949e# restore some SPI controller registers
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_USR_REGTb4b4b4, Te6edf3old_spi_usrTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3SPI_USR2_REGTb4b4b4, Te6edf3old_spi_usr2Tb4b4b4)
Tff7b72return Te6edf3status

Tff7b72def Td2a8ffread_statusTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3num_bytesTff7b72=T79c0ff2Tb4b4b4)Tb4b4b4:
T8b949e"""Read up to 24 bits (num_bytes) of SPI flash status register contents
via RDSR, RDSR2, RDSR3 commands

Not all SPI flash supports all three commands. The upper 1 or 2
bytes may be 0xFF.
"""
Te6edf3SPIFLASH_RDSR Tff7b72= T79c0ff0x05
Te6edf3SPIFLASH_RDSR2 Tff7b72= T79c0ff0x35
Te6edf3SPIFLASH_RDSR3 Tff7b72= T79c0ff0x15

Te6edf3status Tff7b72= T79c0ff0
Te6edf3shift Tff7b72= T79c0ff0
Tff7b72for Te6edf3cmd Tff7b72in Tb4b4b4[Te6edf3SPIFLASH_RDSRTb4b4b4, Te6edf3SPIFLASH_RDSR2Tb4b4b4, Te6edf3SPIFLASH_RDSR3Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4:Te6edf3num_bytesTb4b4b4]Tb4b4b4:
Te6edf3status Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3read_bitsTff7b72=T79c0ff8Tb4b4b4) Tff7b72<< Te6edf3shift
Te6edf3shift Tff7b72+Tff7b72= T79c0ff8
Tff7b72return Te6edf3status

Tff7b72def Td2a8ffwrite_statusTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_statusTb4b4b4, Te6edf3num_bytesTff7b72=T79c0ff2Tb4b4b4, Te6edf3set_non_volatileTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e"""Write up to 24 bits (num_bytes) of new status register

num_bytes can be 1, 2 or 3.

Not all flash supports the additional commands to write the
second and third byte of the status register. When writing 2
bytes, esptool also sends a 16-byte WRSR command (as some
flash types use this instead of WRSR2.)

If the set_non_volatile flag is set, non-volatile bits will
be set as well as volatile ones (WREN used instead of WEVSR).

"""
Te6edf3SPIFLASH_WRSR Tff7b72= T79c0ff0x01
Te6edf3SPIFLASH_WRSR2 Tff7b72= T79c0ff0x31
Te6edf3SPIFLASH_WRSR3 Tff7b72= T79c0ff0x11
Te6edf3SPIFLASH_WEVSR Tff7b72= T79c0ff0x50
Te6edf3SPIFLASH_WREN Tff7b72= T79c0ff0x06
Te6edf3SPIFLASH_WRDI Tff7b72= T79c0ff0x04

Te6edf3enable_cmd Tff7b72= Te6edf3SPIFLASH_WREN Tff7b72if Te6edf3set_non_volatile Tff7b72else Te6edf3SPIFLASH_WEVSR

T8b949e# try using a 16-bit WRSR (not supported by all chips)
T8b949e# this may be redundant, but shouldn't hurt
Tff7b72if Te6edf3num_bytes Tff7b72== T79c0ff2Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3enable_cmdTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3SPIFLASH_WRSRTb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff<HTa5d6ff"Tb4b4b4, Te6edf3new_statusTb4b4b4)Tb4b4b4)

T8b949e# also try using individual commands (also not supported by all chips for num_bytes 2 & 3)
Tff7b72for Te6edf3cmd Tff7b72in Tb4b4b4[Te6edf3SPIFLASH_WRSRTb4b4b4, Te6edf3SPIFLASH_WRSR2Tb4b4b4, Te6edf3SPIFLASH_WRSR3Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4:Te6edf3num_bytesTb4b4b4]Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3enable_cmdTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ffBTa5d6ff"Tb4b4b4, Te6edf3new_status Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4)
Te6edf3new_status Tff7b72>>Tff7b72= T79c0ff8

Tff7b72selfTff7b72.Td2a8ffrun_spiflash_commandTb4b4b4(Te6edf3SPIFLASH_WRDITb4b4b4)

Tff7b72def Td2a8ffget_crystal_freqTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Figure out the crystal frequency from the UART clock divider
T8b949e# Returns a normalized value in integer MHz (40 or 26 are the only supported values)
T8b949e#
T8b949e# The logic here is:
T8b949e# - We know that our baud rate and the ESP UART baud rate are roughly the same, or we couldn't communicate
T8b949e# - We can read the UART clock divider register to know how the ESP derives this from the APB bus frequency
T8b949e# - Multiplying these two together gives us the bus frequency which is either the crystal frequency (ESP32)
T8b949e# or double the crystal frequency (ESP8266). See the self.XTAL_CLK_DIVIDER parameter for this factor.
Te6edf3uart_div Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffUART_CLKDIV_REGTb4b4b4) Tff7b72& Tff7b72selfTff7b72.Td2a8ffUART_CLKDIV_MASK
Te6edf3est_xtal Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ff_portTff7b72.Td2a8ffbaudrate Tff7b72* Te6edf3uart_divTb4b4b4) Tff7b72/ T79c0ff1e6 Tff7b72/ Tff7b72selfTff7b72.Td2a8ffXTAL_CLK_DIVIDER
Te6edf3norm_xtal Tff7b72= T79c0ff40 Tff7b72if Te6edf3est_xtal Tff7b72> T79c0ff33 Tff7b72else T79c0ff26
Tff7b72if Tffa657absTb4b4b4(Te6edf3norm_xtal Tff7b72- Te6edf3est_xtalTb4b4b4) Tff7b72> T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWARNING: Detected crystal freq Tffd700%.2fTa5d6ffMHz is quite different to normalized freq Tffd700%dTa5d6ffMHz. Unsupported crystal in use?Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3est_xtalTb4b4b4, Te6edf3norm_xtalTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3norm_xtal

Tff7b72def Td2a8ffhard_resetTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffHard resetting via RTS pin...Ta5d6ff'Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# EN->LOW
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.1Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4)

Tff7b72def Td2a8ffsoft_resetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3stay_in_bootloaderTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Tff7b72if Te6edf3stay_in_bootloaderTb4b4b4:
Tff7b72return T8b949e# ROM bootloader is already in bootloader!
Tff7b72elseTb4b4b4:
T8b949e# 'run user code' is as close to a soft reset as we can do
Tff7b72selfTff7b72.Td2a8ffflash_beginTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffflash_finishTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72if Te6edf3stay_in_bootloaderTb4b4b4:
T8b949e# soft resetting from the stub loader
T8b949e# will re-load the ROM bootloader
Tff7b72selfTff7b72.Td2a8ffflash_beginTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffflash_finishTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffCHIP_NAME Tff7b72!= Ta5d6ff"Ta5d6ffESP8266Ta5d6ff"Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffSoft resetting is currently only supported on ESP8266Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# running user code from stub loader requires some hacks
T8b949e# in the stub loader
Tff7b72selfTff7b72.Td2a8ffcommandTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_RUN_USER_CODETb4b4b4, Te6edf3wait_responseTff7b72=Tff7b72FalseTb4b4b4)


Tff7b72class T56d364ESP8266ROMTb4b4b4(Te6edf3ESPLoaderTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP8266 ROM bootloader
"""
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP8266Ta5d6ff"
Te6edf3IS_STUB Tff7b72= Tff7b72False

Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0xfff0c101Tb4b4b4]

T8b949e# OTP ROM addresses
Te6edf3ESP_OTP_MAC0 Tff7b72= T79c0ff0x3ff00050
Te6edf3ESP_OTP_MAC1 Tff7b72= T79c0ff0x3ff00054
Te6edf3ESP_OTP_MAC3 Tff7b72= T79c0ff0x3ff0005c

Te6edf3SPI_REG_BASE Tff7b72= T79c0ff0x60000200
Te6edf3SPI_USR_OFFS Tff7b72= T79c0ff0x1c
Te6edf3SPI_USR1_OFFS Tff7b72= T79c0ff0x20
Te6edf3SPI_USR2_OFFS Tff7b72= T79c0ff0x24
Te6edf3SPI_MOSI_DLEN_OFFS Tff7b72= Tff7b72None
Te6edf3SPI_MISO_DLEN_OFFS Tff7b72= Tff7b72None
Te6edf3SPI_W0_OFFS Tff7b72= T79c0ff0x40

Te6edf3UART_CLKDIV_REG Tff7b72= T79c0ff0x60000014

Te6edf3XTAL_CLK_DIVIDER Tff7b72= T79c0ff2

Te6edf3FLASH_SIZES Tff7b72= Tb4b4b4{
Ta5d6ff'Ta5d6ff512KBTa5d6ff'Tb4b4b4: T79c0ff0x00Tb4b4b4,
Ta5d6ff'Ta5d6ff256KBTa5d6ff'Tb4b4b4: T79c0ff0x10Tb4b4b4,
Ta5d6ff'Ta5d6ff1MBTa5d6ff'Tb4b4b4: T79c0ff0x20Tb4b4b4,
Ta5d6ff'Ta5d6ff2MBTa5d6ff'Tb4b4b4: T79c0ff0x30Tb4b4b4,
Ta5d6ff'Ta5d6ff4MBTa5d6ff'Tb4b4b4: T79c0ff0x40Tb4b4b4,
Ta5d6ff'Ta5d6ff2MB-c1Ta5d6ff'Tb4b4b4: T79c0ff0x50Tb4b4b4,
Ta5d6ff'Ta5d6ff4MB-c1Ta5d6ff'Tb4b4b4: T79c0ff0x60Tb4b4b4,
Ta5d6ff'Ta5d6ff8MBTa5d6ff'Tb4b4b4: T79c0ff0x80Tb4b4b4,
Ta5d6ff'Ta5d6ff16MBTa5d6ff'Tb4b4b4: T79c0ff0x90Tb4b4b4,
Tb4b4b4}

Te6edf3BOOTLOADER_FLASH_OFFSET Tff7b72= T79c0ff0

Te6edf3MEMORY_MAP Tff7b72= Tb4b4b4[Tb4b4b4[T79c0ff0x3FF00000Tb4b4b4, T79c0ff0x3FF00010Tb4b4b4, Ta5d6ff"Ta5d6ffDPORTTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FFE8000Tb4b4b4, T79c0ff0x40000000Tb4b4b4, Ta5d6ff"Ta5d6ffDRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40100000Tb4b4b4, T79c0ff0x40108000Tb4b4b4, Ta5d6ff"Ta5d6ffIRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40201010Tb4b4b4, T79c0ff0x402E1010Tb4b4b4, Ta5d6ff"Ta5d6ffIROMTa5d6ff"Tb4b4b4]Tb4b4b4]

Tff7b72def Td2a8ffget_efusesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Return the 128 bits of ESP8266 efuse as a single Python integer
Te6edf3result Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(T79c0ff0x3ff0005cTb4b4b4) Tff7b72<< T79c0ff96
Te6edf3result Tff7b72|Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(T79c0ff0x3ff00058Tb4b4b4) Tff7b72<< T79c0ff64
Te6edf3result Tff7b72|Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(T79c0ff0x3ff00054Tb4b4b4) Tff7b72<< T79c0ff32
Te6edf3result Tff7b72|Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(T79c0ff0x3ff00050Tb4b4b4)
Tff7b72return Te6edf3result

Tff7b72def Td2a8ff_get_flash_sizeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3efusesTb4b4b4)Tb4b4b4:
T8b949e# rX_Y = EFUSE_DATA_OUTX[Y]
Te6edf3r0_4 Tff7b72= Tb4b4b4(Te6edf3efuses Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff4Tb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff0
Te6edf3r3_25 Tff7b72= Tb4b4b4(Te6edf3efuses Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff121Tb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff0
Te6edf3r3_26 Tff7b72= Tb4b4b4(Te6edf3efuses Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff122Tb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff0
Te6edf3r3_27 Tff7b72= Tb4b4b4(Te6edf3efuses Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff123Tb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff0

Tff7b72if Te6edf3r0_4 Tff7b72and Tff7b72not Te6edf3r3_25Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3r3_27 Tff7b72and Tff7b72not Te6edf3r3_26Tb4b4b4:
Tff7b72return T79c0ff1
Tff7b72elif Tff7b72not Te6edf3r3_27 Tff7b72and Te6edf3r3_26Tb4b4b4:
Tff7b72return T79c0ff2
Tff7b72if Tff7b72not Te6edf3r0_4 Tff7b72and Te6edf3r3_25Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3r3_27 Tff7b72and Tff7b72not Te6edf3r3_26Tb4b4b4:
Tff7b72return T79c0ff2
Tff7b72elif Tff7b72not Te6edf3r3_27 Tff7b72and Te6edf3r3_26Tb4b4b4:
Tff7b72return T79c0ff4
Tff7b72return Tff7b72-T79c0ff1

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3efuses Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_efusesTb4b4b4(Tb4b4b4)
Te6edf3is_8285 Tff7b72= Tb4b4b4(Te6edf3efuses Tff7b72& Tb4b4b4(Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff4Tb4b4b4) Tff7b72| T79c0ff1 Tff7b72<< T79c0ff80Tb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff0 T8b949e# One or the other efuse bit is set for ESP8285
Tff7b72if Te6edf3is_8285Tb4b4b4:
Te6edf3flash_size Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_flash_sizeTb4b4b4(Te6edf3efusesTb4b4b4)
Te6edf3max_temp Tff7b72= Tb4b4b4(Te6edf3efuses Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff5Tb4b4b4)Tb4b4b4) Tff7b72!= T79c0ff0 T8b949e# This efuse bit identifies the max flash temperature
Te6edf3chip_name Tff7b72= Tb4b4b4{
T79c0ff1Tb4b4b4: Ta5d6ff"Ta5d6ffESP8285H08Ta5d6ff" Tff7b72if Te6edf3max_temp Tff7b72else Ta5d6ff"Ta5d6ffESP8285N08Ta5d6ff"Tb4b4b4,
T79c0ff2Tb4b4b4: Ta5d6ff"Ta5d6ffESP8285H16Ta5d6ff" Tff7b72if Te6edf3max_temp Tff7b72else Ta5d6ff"Ta5d6ffESP8285N16Ta5d6ff"
Tb4b4b4}Tff7b72.Td2a8ffgetTb4b4b4(Te6edf3flash_sizeTb4b4b4, Ta5d6ff"Ta5d6ffESP8285Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3chip_name
Tff7b72return Ta5d6ff"Ta5d6ffESP8266EXTa5d6ff"

Tff7b72def Td2a8ffget_chip_featuresTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3features Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffWiFiTa5d6ff"Tb4b4b4]
Tff7b72if Ta5d6ff"Ta5d6ffESP8285Ta5d6ff" Tff7b72in Tff7b72selfTff7b72.Td2a8ffget_chip_descriptionTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffEmbedded FlashTa5d6ff"Tb4b4b4]
Tff7b72return Te6edf3features

Tff7b72def Td2a8ffflash_spi_attachTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3hspi_argTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Tffa657superTb4b4b4(Te6edf3ESP8266ROMTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ffflash_spi_attachTb4b4b4(Te6edf3hspi_argTb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# ESP8266 ROM has no flash_spi_attach command in serial protocol,
T8b949e# but flash_begin will do it
Tff7b72selfTff7b72.Td2a8ffflash_beginTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)

Tff7b72def Td2a8ffflash_set_parametersTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
T8b949e# not implemented in ROM, but OK to silently skip for ROM
Tff7b72if Tff7b72selfTff7b72.Td2a8ffIS_STUBTb4b4b4:
Tffa657superTb4b4b4(Te6edf3ESP8266ROMTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ffflash_set_parametersTb4b4b4(Te6edf3sizeTb4b4b4)

Tff7b72def Td2a8ffchip_idTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e""" Read Chip ID from efuse - the equivalent of the SDK system_get_chip_id() function """
Te6edf3id0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_OTP_MAC0Tb4b4b4)
Te6edf3id1 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_OTP_MAC1Tb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3id0 Tff7b72>> T79c0ff24Tb4b4b4) Tff7b72| Tb4b4b4(Tb4b4b4(Te6edf3id1 Tff7b72& Te6edf3MAX_UINT24Tb4b4b4) Tff7b72<< T79c0ff8Tb4b4b4)

Tff7b72def Td2a8ffread_macTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e""" Read MAC from OTP ROM """
Te6edf3mac0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_OTP_MAC0Tb4b4b4)
Te6edf3mac1 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_OTP_MAC1Tb4b4b4)
Te6edf3mac3 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffESP_OTP_MAC3Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3mac3 Tff7b72!= T79c0ff0Tb4b4b4)Tb4b4b4:
Te6edf3oui Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3mac3 Tff7b72>> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4, Tb4b4b4(Te6edf3mac3 Tff7b72>> T79c0ff8Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4, Te6edf3mac3 Tff7b72& T79c0ff0xffTb4b4b4)
Tff7b72elif Tb4b4b4(Tb4b4b4(Te6edf3mac1 Tff7b72>> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3oui Tff7b72= Tb4b4b4(T79c0ff0x18Tb4b4b4, T79c0ff0xfeTb4b4b4, T79c0ff0x34Tb4b4b4)
Tff7b72elif Tb4b4b4(Tb4b4b4(Te6edf3mac1 Tff7b72>> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4) Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3oui Tff7b72= Tb4b4b4(T79c0ff0xacTb4b4b4, T79c0ff0xd0Tb4b4b4, T79c0ff0x74Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnknown OUITa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3oui Tff7b72+ Tb4b4b4(Tb4b4b4(Te6edf3mac1 Tff7b72>> T79c0ff8Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4, Te6edf3mac1 Tff7b72& T79c0ff0xffTb4b4b4, Tb4b4b4(Te6edf3mac0 Tff7b72>> T79c0ff24Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4)

Tff7b72def Td2a8ffget_erase_sizeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
T8b949e""" Calculate an erase size given a specific size in bytes.

Provides a workaround for the bootloader erase bug."""

Te6edf3sectors_per_block Tff7b72= T79c0ff16
Te6edf3sector_size Tff7b72= Tff7b72selfTff7b72.Td2a8ffFLASH_SECTOR_SIZE
Te6edf3num_sectors Tff7b72= Tb4b4b4(Te6edf3size Tff7b72+ Te6edf3sector_size Tff7b72- T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Te6edf3sector_size
Te6edf3start_sector Tff7b72= Te6edf3offset Tff7b72/Tff7b72/ Te6edf3sector_size

Te6edf3head_sectors Tff7b72= Te6edf3sectors_per_block Tff7b72- Tb4b4b4(Te6edf3start_sector Tff7b72% Te6edf3sectors_per_blockTb4b4b4)
Tff7b72if Te6edf3num_sectors Tff7b72< Te6edf3head_sectorsTb4b4b4:
Te6edf3head_sectors Tff7b72= Te6edf3num_sectors

Tff7b72if Te6edf3num_sectors Tff7b72< T79c0ff2 Tff7b72* Te6edf3head_sectorsTb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3num_sectors Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ T79c0ff2 Tff7b72* Te6edf3sector_size
Tff7b72elseTb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3num_sectors Tff7b72- Te6edf3head_sectorsTb4b4b4) Tff7b72* Te6edf3sector_size

Tff7b72def Td2a8ffoverride_vddsdioTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_voltageTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3NotImplementedInROMErrorTb4b4b4(Ta5d6ff"Ta5d6ffOverriding VDDSDIO setting only applies to ESP32Ta5d6ff"Tb4b4b4)


Tff7b72class T56d364ESP8266StubLoaderTb4b4b4(Te6edf3ESP8266ROMTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP8266 stub loader, runs on top of ROM.
"""
Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x4000 T8b949e# matches MAX_WRITE_BLOCK in stub_loader.c
Te6edf3IS_STUB Tff7b72= Tff7b72True

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rom_loaderTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ffsecure_download_mode
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_port
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_trace_enabled
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# resets _slip_reader

Tff7b72def Td2a8ffget_erase_sizeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3size T8b949e# stub doesn't have same size bug as ROM loader


Te6edf3ESP8266ROMTff7b72.Td2a8ffSTUB_CLASS Tff7b72= Te6edf3ESP8266StubLoader


Tff7b72class T56d364ESP32ROMTb4b4b4(Te6edf3ESPLoaderTb4b4b4)Tb4b4b4:
T8b949e"""Access class for ESP32 ROM bootloader

"""
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32Ta5d6ff"
Te6edf3IMAGE_CHIP_ID Tff7b72= T79c0ff0
Te6edf3IS_STUB Tff7b72= Tff7b72False

Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0x00f01d83Tb4b4b4]

Te6edf3IROM_MAP_START Tff7b72= T79c0ff0x400d0000
Te6edf3IROM_MAP_END Tff7b72= T79c0ff0x40400000

Te6edf3DROM_MAP_START Tff7b72= T79c0ff0x3F400000
Te6edf3DROM_MAP_END Tff7b72= T79c0ff0x3F800000

T8b949e# ESP32 uses a 4 byte status reply
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff4

Te6edf3SPI_REG_BASE Tff7b72= T79c0ff0x3ff42000
Te6edf3SPI_USR_OFFS Tff7b72= T79c0ff0x1c
Te6edf3SPI_USR1_OFFS Tff7b72= T79c0ff0x20
Te6edf3SPI_USR2_OFFS Tff7b72= T79c0ff0x24
Te6edf3SPI_MOSI_DLEN_OFFS Tff7b72= T79c0ff0x28
Te6edf3SPI_MISO_DLEN_OFFS Tff7b72= T79c0ff0x2c
Te6edf3EFUSE_RD_REG_BASE Tff7b72= T79c0ff0x3ff5a000

Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG Tff7b72= Te6edf3EFUSE_RD_REG_BASE Tff7b72+ T79c0ff0x18
Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff7Tb4b4b4) T8b949e# EFUSE_RD_DISABLE_DL_ENCRYPT

Te6edf3DR_REG_SYSCON_BASE Tff7b72= T79c0ff0x3ff66000

Te6edf3SPI_W0_OFFS Tff7b72= T79c0ff0x80

Te6edf3UART_CLKDIV_REG Tff7b72= T79c0ff0x3ff40014

Te6edf3XTAL_CLK_DIVIDER Tff7b72= T79c0ff1

Te6edf3FLASH_SIZES Tff7b72= Tb4b4b4{
Ta5d6ff'Ta5d6ff1MBTa5d6ff'Tb4b4b4: T79c0ff0x00Tb4b4b4,
Ta5d6ff'Ta5d6ff2MBTa5d6ff'Tb4b4b4: T79c0ff0x10Tb4b4b4,
Ta5d6ff'Ta5d6ff4MBTa5d6ff'Tb4b4b4: T79c0ff0x20Tb4b4b4,
Ta5d6ff'Ta5d6ff8MBTa5d6ff'Tb4b4b4: T79c0ff0x30Tb4b4b4,
Ta5d6ff'Ta5d6ff16MBTa5d6ff'Tb4b4b4: T79c0ff0x40
Tb4b4b4}

Te6edf3BOOTLOADER_FLASH_OFFSET Tff7b72= T79c0ff0x1000

Te6edf3OVERRIDE_VDDSDIO_CHOICES Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ff1.8VTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff1.9VTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffOFFTa5d6ff"Tb4b4b4]

Te6edf3MEMORY_MAP Tff7b72= Tb4b4b4[Tb4b4b4[T79c0ff0x00000000Tb4b4b4, T79c0ff0x00010000Tb4b4b4, Ta5d6ff"Ta5d6ffPADDINGTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3F400000Tb4b4b4, T79c0ff0x3F800000Tb4b4b4, Ta5d6ff"Ta5d6ffDROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3F800000Tb4b4b4, T79c0ff0x3FC00000Tb4b4b4, Ta5d6ff"Ta5d6ffEXTRAM_DATATa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FF80000Tb4b4b4, T79c0ff0x3FF82000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FF90000Tb4b4b4, T79c0ff0x40000000Tb4b4b4, Ta5d6ff"Ta5d6ffBYTE_ACCESSIBLETa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FFAE000Tb4b4b4, T79c0ff0x40000000Tb4b4b4, Ta5d6ff"Ta5d6ffDRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FFE0000Tb4b4b4, T79c0ff0x3FFFFFFCTb4b4b4, Ta5d6ff"Ta5d6ffDIRAM_DRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40000000Tb4b4b4, T79c0ff0x40070000Tb4b4b4, Ta5d6ff"Ta5d6ffIROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40070000Tb4b4b4, T79c0ff0x40078000Tb4b4b4, Ta5d6ff"Ta5d6ffCACHE_PROTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40078000Tb4b4b4, T79c0ff0x40080000Tb4b4b4, Ta5d6ff"Ta5d6ffCACHE_APPTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40080000Tb4b4b4, T79c0ff0x400A0000Tb4b4b4, Ta5d6ff"Ta5d6ffIRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x400A0000Tb4b4b4, T79c0ff0x400BFFFCTb4b4b4, Ta5d6ff"Ta5d6ffDIRAM_IRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x400C0000Tb4b4b4, T79c0ff0x400C2000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_IRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x400D0000Tb4b4b4, T79c0ff0x40400000Tb4b4b4, Ta5d6ff"Ta5d6ffIROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x50000000Tb4b4b4, T79c0ff0x50002000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DATATa5d6ff"Tb4b4b4]Tb4b4b4]

Te6edf3FLASH_ENCRYPTED_WRITE_ALIGN Tff7b72= T79c0ff32

T8b949e""" Try to read the BLOCK1 (encryption key) and check if it is valid """

Tff7b72def Td2a8ffis_flash_encryption_key_validTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:

T8b949e""" Bit 0 of efuse_rd_disable[3:0] is mapped to BLOCK1
this bit is at position 16 in EFUSE_BLK0_RDATA0_REG """
Te6edf3word0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3rd_disable Tff7b72= Tb4b4b4(Te6edf3word0 Tff7b72>> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0x1

T8b949e# reading of BLOCK1 is NOT ALLOWED so we assume valid key is programmed
Tff7b72if Te6edf3rd_disableTb4b4b4:
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
T8b949e# reading of BLOCK1 is ALLOWED so we will read and verify for non-zero.
T8b949e# When ESP32 has not generated AES/encryption key in BLOCK1, the contents will be readable and 0.
T8b949e# If the flash encryption is enabled it is expected to have a valid non-zero key. We break out on
T8b949e# first occurance of non-zero value
Te6edf3key_word Tff7b72= Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72* T79c0ff7
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Tffa657lenTb4b4b4(Te6edf3key_wordTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3key_wordTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff14 Tff7b72+ Te6edf3iTb4b4b4)
T8b949e# key is non-zero so break & return
Tff7b72if Te6edf3key_wordTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffget_flash_crypt_configTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e""" For flash encryption related commands we need to make sure
user has programmed all the relevant efuse correctly so before
writing encrypted write_flash_encrypt esptool will verify the values
of flash_crypt_config to be non zero if they are not read
protected. If the values are zero a warning will be printed

bit 3 in efuse_rd_disable[3:0] is mapped to flash_crypt_config
this bit is at position 19 in EFUSE_BLK0_RDATA0_REG """
Te6edf3word0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3rd_disable Tff7b72= Tb4b4b4(Te6edf3word0 Tff7b72>> T79c0ff19Tb4b4b4) Tff7b72& T79c0ff0x1

Tff7b72if Te6edf3rd_disable Tff7b72== T79c0ff0Tb4b4b4:
T8b949e""" we can read the flash_crypt_config efuse value
so go & read it (EFUSE_BLK0_RDATA5_REG[31:28]) """
Te6edf3word5 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff5Tb4b4b4)
Te6edf3word5 Tff7b72= Tb4b4b4(Te6edf3word5 Tff7b72>> T79c0ff28Tb4b4b4) Tff7b72& T79c0ff0xF
Tff7b72return Te6edf3word5
Tff7b72elseTb4b4b4:
T8b949e# if read of the efuse is disabled we assume it is set correctly
Tff7b72return T79c0ff0xF

Tff7b72def Td2a8ffget_encrypted_download_disabledTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REGTb4b4b4) Tff7b72& Tff7b72selfTff7b72.Td2a8ffEFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPTTb4b4b4:
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffget_pkg_versionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3word3 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff3Tb4b4b4)
Te6edf3pkg_version Tff7b72= Tb4b4b4(Te6edf3word3 Tff7b72>> T79c0ff9Tb4b4b4) Tff7b72& T79c0ff0x07
Te6edf3pkg_version Tff7b72+Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3word3 Tff7b72>> T79c0ff2Tb4b4b4) Tff7b72& T79c0ff0x1Tb4b4b4) Tff7b72<< T79c0ff3
Tff7b72return Te6edf3pkg_version

Tff7b72def Td2a8ffget_chip_revisionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3word3 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff3Tb4b4b4)
Te6edf3word5 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff5Tb4b4b4)
Te6edf3apb_ctl_date Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffDR_REG_SYSCON_BASE Tff7b72+ T79c0ff0x7CTb4b4b4)

Te6edf3rev_bit0 Tff7b72= Tb4b4b4(Te6edf3word3 Tff7b72>> T79c0ff15Tb4b4b4) Tff7b72& T79c0ff0x1
Te6edf3rev_bit1 Tff7b72= Tb4b4b4(Te6edf3word5 Tff7b72>> T79c0ff20Tb4b4b4) Tff7b72& T79c0ff0x1
Te6edf3rev_bit2 Tff7b72= Tb4b4b4(Te6edf3apb_ctl_date Tff7b72>> T79c0ff31Tb4b4b4) Tff7b72& T79c0ff0x1
Tff7b72if Te6edf3rev_bit0Tb4b4b4:
Tff7b72if Te6edf3rev_bit1Tb4b4b4:
Tff7b72if Te6edf3rev_bit2Tb4b4b4:
Tff7b72return T79c0ff3
Tff7b72elseTb4b4b4:
Tff7b72return T79c0ff2
Tff7b72elseTb4b4b4:
Tff7b72return T79c0ff1
Tff7b72return T79c0ff0

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3pkg_version Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_pkg_versionTb4b4b4(Tb4b4b4)
Te6edf3chip_revision Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_chip_revisionTb4b4b4(Tb4b4b4)
Te6edf3rev3 Tff7b72= Tb4b4b4(Te6edf3chip_revision Tff7b72== T79c0ff3Tb4b4b4)
Te6edf3single_core Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff3Tb4b4b4) Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff0Tb4b4b4) T8b949e# CHIP_VER DIS_APP_CPU

Te6edf3chip_name Tff7b72= Tb4b4b4{
T79c0ff0Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-S0WDQ6Ta5d6ff" Tff7b72if Te6edf3single_core Tff7b72else Ta5d6ff"Ta5d6ffESP32-D0WDQ6Ta5d6ff"Tb4b4b4,
T79c0ff1Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-S0WDTa5d6ff" Tff7b72if Te6edf3single_core Tff7b72else Ta5d6ff"Ta5d6ffESP32-D0WDTa5d6ff"Tb4b4b4,
T79c0ff2Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-D2WDTa5d6ff"Tb4b4b4,
T79c0ff4Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-U4WDHTa5d6ff"Tb4b4b4,
T79c0ff5Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-PICO-V3Ta5d6ff" Tff7b72if Te6edf3rev3 Tff7b72else Ta5d6ff"Ta5d6ffESP32-PICO-D4Ta5d6ff"Tb4b4b4,
T79c0ff6Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-PICO-V3-02Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tff7b72.Td2a8ffgetTb4b4b4(Te6edf3pkg_versionTb4b4b4, Ta5d6ff"Ta5d6ffunknown ESP32Ta5d6ff"Tb4b4b4)

T8b949e# ESP32-D0WD-V3, ESP32-D0WDQ6-V3
Tff7b72if Te6edf3chip_nameTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffESP32-D0WDTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3rev3Tb4b4b4:
Te6edf3chip_name Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff-V3Ta5d6ff"

Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff (revision Tffd700%dTa5d6ff)Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3chip_nameTb4b4b4, Te6edf3chip_revisionTb4b4b4)

Tff7b72def Td2a8ffget_chip_featuresTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3features Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffWiFiTa5d6ff"Tb4b4b4]
Te6edf3word3 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff3Tb4b4b4)

T8b949e# names of variables in this section are lowercase
T8b949e# versions of EFUSE names as documented in TRM and
T8b949e# ESP-IDF efuse_reg.h

Te6edf3chip_ver_dis_bt Tff7b72= Te6edf3word3 Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff1Tb4b4b4)
Tff7b72if Te6edf3chip_ver_dis_bt Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffBTTa5d6ff"Tb4b4b4]

Te6edf3chip_ver_dis_app_cpu Tff7b72= Te6edf3word3 Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff0Tb4b4b4)
Tff7b72if Te6edf3chip_ver_dis_app_cpuTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffSingle CoreTa5d6ff"Tb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffDual CoreTa5d6ff"Tb4b4b4]

Te6edf3chip_cpu_freq_rated Tff7b72= Te6edf3word3 Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff13Tb4b4b4)
Tff7b72if Te6edf3chip_cpu_freq_ratedTb4b4b4:
Te6edf3chip_cpu_freq_low Tff7b72= Te6edf3word3 Tff7b72& Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff12Tb4b4b4)
Tff7b72if Te6edf3chip_cpu_freq_lowTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ff160MHzTa5d6ff"Tb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ff240MHzTa5d6ff"Tb4b4b4]

Te6edf3pkg_version Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_pkg_versionTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3pkg_version Tff7b72in Tb4b4b4[T79c0ff2Tb4b4b4, T79c0ff4Tb4b4b4, T79c0ff5Tb4b4b4, T79c0ff6Tb4b4b4]Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffEmbedded FlashTa5d6ff"Tb4b4b4]

Tff7b72if Te6edf3pkg_version Tff7b72== T79c0ff6Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffEmbedded PSRAMTa5d6ff"Tb4b4b4]

Te6edf3word4 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff4Tb4b4b4)
Te6edf3adc_vref Tff7b72= Tb4b4b4(Te6edf3word4 Tff7b72>> T79c0ff8Tb4b4b4) Tff7b72& T79c0ff0x1F
Tff7b72if Te6edf3adc_vrefTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffVRef calibration in efuseTa5d6ff"Tb4b4b4]

Te6edf3blk3_part_res Tff7b72= Te6edf3word3 Tff7b72>> T79c0ff14 Tff7b72& T79c0ff0x1
Tff7b72if Te6edf3blk3_part_resTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffBLK3 partially reservedTa5d6ff"Tb4b4b4]

Te6edf3word6 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff6Tb4b4b4)
Te6edf3coding_scheme Tff7b72= Te6edf3word6 Tff7b72& T79c0ff0x3
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffCoding Scheme Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4{
T79c0ff0Tb4b4b4: Ta5d6ff"Ta5d6ffNoneTa5d6ff"Tb4b4b4,
T79c0ff1Tb4b4b4: Ta5d6ff"Ta5d6ff3/4Ta5d6ff"Tb4b4b4,
T79c0ff2Tb4b4b4: Ta5d6ff"Ta5d6ffRepeat (UNSUPPORTED)Ta5d6ff"Tb4b4b4,
T79c0ff3Tb4b4b4: Ta5d6ff"Ta5d6ffInvalidTa5d6ff"Tb4b4b4}Tb4b4b4[Te6edf3coding_schemeTb4b4b4]Tb4b4b4]

Tff7b72return Te6edf3features

Tff7b72def Td2a8ffread_efuseTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nTb4b4b4)Tb4b4b4:
T8b949e""" Read the nth word of the ESP3x EFUSE region. """
Tff7b72return Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_RD_REG_BASE Tff7b72+ Tb4b4b4(T79c0ff4 Tff7b72* Te6edf3nTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffchip_idTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3NotSupportedErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffchip_idTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffread_macTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e""" Read MAC from EFUSE region """
Te6edf3words Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff2Tb4b4b4)Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffread_efuseTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4]
Te6edf3bitstring Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff>IITa5d6ff"Tb4b4b4, Tff7b72*Te6edf3wordsTb4b4b4)
Te6edf3bitstring Tff7b72= Te6edf3bitstringTb4b4b4[T79c0ff2Tb4b4b4:T79c0ff8Tb4b4b4] T8b949e# trim the 2 byte CRC
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657tupleTb4b4b4(Tffa657ordTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Te6edf3bitstringTb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4: T8b949e# Python 3, bitstring elements are already bytes
Tff7b72return Tffa657tupleTb4b4b4(Te6edf3bitstringTb4b4b4)

Tff7b72def Td2a8ffget_erase_sizeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3size

Tff7b72def Td2a8ffoverride_vddsdioTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_voltageTb4b4b4)Tb4b4b4:
Te6edf3new_voltage Tff7b72= Te6edf3new_voltageTff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3new_voltage Tff7b72not Tff7b72in Tff7b72selfTff7b72.Td2a8ffOVERRIDE_VDDSDIO_CHOICESTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffThe only accepted VDDSDIO overrides are Ta5d6ff'Ta5d6ff1.8VTa5d6ff'Ta5d6ff, Ta5d6ff'Ta5d6ff1.9VTa5d6ff'Ta5d6ff and Ta5d6ff'Ta5d6ffOFFTa5d6ff'Ta5d6ff"Tb4b4b4)
Te6edf3RTC_CNTL_SDIO_CONF_REG Tff7b72= T79c0ff0x3ff48074
Te6edf3RTC_CNTL_XPD_SDIO_REG Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff31Tb4b4b4)
Te6edf3RTC_CNTL_DREFH_SDIO_M Tff7b72= Tb4b4b4(T79c0ff3 Tff7b72<< T79c0ff29Tb4b4b4)
Te6edf3RTC_CNTL_DREFM_SDIO_M Tff7b72= Tb4b4b4(T79c0ff3 Tff7b72<< T79c0ff27Tb4b4b4)
Te6edf3RTC_CNTL_DREFL_SDIO_M Tff7b72= Tb4b4b4(T79c0ff3 Tff7b72<< T79c0ff25Tb4b4b4)
T8b949e# RTC_CNTL_SDIO_TIEH = (1 << 23) # not used here, setting TIEH=1 would set 3.3V output, not safe for esptool.py to do
Te6edf3RTC_CNTL_SDIO_FORCE Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff22Tb4b4b4)
Te6edf3RTC_CNTL_SDIO_PD_EN Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<< T79c0ff21Tb4b4b4)

Te6edf3reg_val Tff7b72= Te6edf3RTC_CNTL_SDIO_FORCE T8b949e# override efuse setting
Te6edf3reg_val Tff7b72|Tff7b72= Te6edf3RTC_CNTL_SDIO_PD_EN
Tff7b72if Te6edf3new_voltage Tff7b72!= Ta5d6ff"Ta5d6ffOFFTa5d6ff"Tb4b4b4:
Te6edf3reg_val Tff7b72|Tff7b72= Te6edf3RTC_CNTL_XPD_SDIO_REG T8b949e# enable internal LDO
Tff7b72if Te6edf3new_voltage Tff7b72== Ta5d6ff"Ta5d6ff1.9VTa5d6ff"Tb4b4b4:
Te6edf3reg_val Tff7b72|Tff7b72= Tb4b4b4(Te6edf3RTC_CNTL_DREFH_SDIO_M Tff7b72| Te6edf3RTC_CNTL_DREFM_SDIO_M Tff7b72| Te6edf3RTC_CNTL_DREFL_SDIO_MTb4b4b4) T8b949e# boost voltage
Tff7b72selfTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3RTC_CNTL_SDIO_CONF_REGTb4b4b4, Te6edf3reg_valTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffVDDSDIO regulator set to Tffd700%sTa5d6ff" Tff7b72% Te6edf3new_voltageTb4b4b4)

Tff7b72def Td2a8ffread_flash_slowTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3lengthTb4b4b4, Te6edf3progress_fnTb4b4b4)Tb4b4b4:
Te6edf3BLOCK_LEN Tff7b72= T79c0ff64 T8b949e# ROM read limit per command (this limit is why it's so slow)

Te6edf3data Tff7b72= Ta5d6ffbTa5d6ff'Ta5d6ff'
Tff7b72while Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< Te6edf3lengthTb4b4b4:
Te6edf3block_len Tff7b72= Tffa657minTb4b4b4(Te6edf3BLOCK_LENTb4b4b4, Te6edf3length Tff7b72- Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)
Te6edf3r Tff7b72= Tff7b72selfTff7b72.Td2a8ffcheck_commandTb4b4b4(Ta5d6ff"Ta5d6ffread flash blockTa5d6ff"Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffESP_READ_FLASH_SLOWTb4b4b4,
Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IITa5d6ff'Tb4b4b4, Te6edf3offset Tff7b72+ Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3block_lenTb4b4b4)Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rTb4b4b4) Tff7b72< Te6edf3block_lenTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffExpected Tffd700%dTa5d6ff byte block, got Tffd700%dTa5d6ff bytes. Serial errors?Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3block_lenTb4b4b4, Tffa657lenTb4b4b4(Te6edf3rTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3data Tff7b72+Tff7b72= Te6edf3rTb4b4b4[Tb4b4b4:Te6edf3block_lenTb4b4b4] T8b949e# command always returns 64 byte buffer, regardless of how many bytes were actually read from flash
Tff7b72if Te6edf3progress_fn Tff7b72and Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72% T79c0ff1024 Tff7b72== T79c0ff0 Tff7b72or Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72== Te6edf3lengthTb4b4b4)Tb4b4b4:
Te6edf3progress_fnTb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3lengthTb4b4b4)
Tff7b72return Te6edf3data


Tff7b72class T56d364ESP32S2ROMTb4b4b4(Te6edf3ESP32ROMTb4b4b4)Tb4b4b4:
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32-S2Ta5d6ff"
Te6edf3IMAGE_CHIP_ID Tff7b72= T79c0ff2

Te6edf3IROM_MAP_START Tff7b72= T79c0ff0x40080000
Te6edf3IROM_MAP_END Tff7b72= T79c0ff0x40b80000
Te6edf3DROM_MAP_START Tff7b72= T79c0ff0x3F000000
Te6edf3DROM_MAP_END Tff7b72= T79c0ff0x3F3F0000

Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0x000007c6Tb4b4b4]

Te6edf3SPI_REG_BASE Tff7b72= T79c0ff0x3f402000
Te6edf3SPI_USR_OFFS Tff7b72= T79c0ff0x18
Te6edf3SPI_USR1_OFFS Tff7b72= T79c0ff0x1c
Te6edf3SPI_USR2_OFFS Tff7b72= T79c0ff0x20
Te6edf3SPI_MOSI_DLEN_OFFS Tff7b72= T79c0ff0x24
Te6edf3SPI_MISO_DLEN_OFFS Tff7b72= T79c0ff0x28
Te6edf3SPI_W0_OFFS Tff7b72= T79c0ff0x58

Te6edf3MAC_EFUSE_REG Tff7b72= T79c0ff0x3f41A044 T8b949e# ESP32-S2 has special block for MAC efuses

Te6edf3UART_CLKDIV_REG Tff7b72= T79c0ff0x3f400014

Te6edf3FLASH_ENCRYPTED_WRITE_ALIGN Tff7b72= T79c0ff16

T8b949e# todo: use espefuse APIs to get this info
Te6edf3EFUSE_BASE Tff7b72= T79c0ff0x3f41A000
Te6edf3EFUSE_RD_REG_BASE Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x030 T8b949e# BLOCK0 read base address

Te6edf3EFUSE_PURPOSE_KEY0_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x34
Te6edf3EFUSE_PURPOSE_KEY0_SHIFT Tff7b72= T79c0ff24
Te6edf3EFUSE_PURPOSE_KEY1_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x34
Te6edf3EFUSE_PURPOSE_KEY1_SHIFT Tff7b72= T79c0ff28
Te6edf3EFUSE_PURPOSE_KEY2_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY2_SHIFT Tff7b72= T79c0ff0
Te6edf3EFUSE_PURPOSE_KEY3_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY3_SHIFT Tff7b72= T79c0ff4
Te6edf3EFUSE_PURPOSE_KEY4_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY4_SHIFT Tff7b72= T79c0ff8
Te6edf3EFUSE_PURPOSE_KEY5_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY5_SHIFT Tff7b72= T79c0ff12

Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG Tff7b72= Te6edf3EFUSE_RD_REG_BASE
Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT Tff7b72= T79c0ff1 Tff7b72<< T79c0ff19

Te6edf3PURPOSE_VAL_XTS_AES256_KEY_1 Tff7b72= T79c0ff2
Te6edf3PURPOSE_VAL_XTS_AES256_KEY_2 Tff7b72= T79c0ff3
Te6edf3PURPOSE_VAL_XTS_AES128_KEY Tff7b72= T79c0ff4

Te6edf3UARTDEV_BUF_NO Tff7b72= T79c0ff0x3ffffd14 T8b949e# Variable in ROM .bss which indicates the port in use
Te6edf3UARTDEV_BUF_NO_USB Tff7b72= T79c0ff2 T8b949e# Value of the above variable indicating that USB is in use

Te6edf3USB_RAM_BLOCK Tff7b72= T79c0ff0x800 T8b949e# Max block size USB CDC is used

Te6edf3GPIO_STRAP_REG Tff7b72= T79c0ff0x3f404038
Te6edf3GPIO_STRAP_SPI_BOOT_MASK Tff7b72= T79c0ff0x8 T8b949e# Not download mode
Te6edf3RTC_CNTL_OPTION1_REG Tff7b72= T79c0ff0x3f408128
Te6edf3RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK Tff7b72= T79c0ff0x1 T8b949e# Is download mode forced over USB?

Te6edf3MEMORY_MAP Tff7b72= Tb4b4b4[Tb4b4b4[T79c0ff0x00000000Tb4b4b4, T79c0ff0x00010000Tb4b4b4, Ta5d6ff"Ta5d6ffPADDINGTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3F000000Tb4b4b4, T79c0ff0x3FF80000Tb4b4b4, Ta5d6ff"Ta5d6ffDROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3F500000Tb4b4b4, T79c0ff0x3FF80000Tb4b4b4, Ta5d6ff"Ta5d6ffEXTRAM_DATATa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FF9E000Tb4b4b4, T79c0ff0x3FFA0000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FF9E000Tb4b4b4, T79c0ff0x40000000Tb4b4b4, Ta5d6ff"Ta5d6ffBYTE_ACCESSIBLETa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FF9E000Tb4b4b4, T79c0ff0x40072000Tb4b4b4, Ta5d6ff"Ta5d6ffMEM_INTERNALTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FFB0000Tb4b4b4, T79c0ff0x40000000Tb4b4b4, Ta5d6ff"Ta5d6ffDRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40000000Tb4b4b4, T79c0ff0x4001A100Tb4b4b4, Ta5d6ff"Ta5d6ffIROM_MASKTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40020000Tb4b4b4, T79c0ff0x40070000Tb4b4b4, Ta5d6ff"Ta5d6ffIRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40070000Tb4b4b4, T79c0ff0x40072000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_IRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40080000Tb4b4b4, T79c0ff0x40800000Tb4b4b4, Ta5d6ff"Ta5d6ffIROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x50000000Tb4b4b4, T79c0ff0x50002000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DATATa5d6ff"Tb4b4b4]Tb4b4b4]

Tff7b72def Td2a8ffget_pkg_versionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3num_word Tff7b72= T79c0ff3
Te6edf3block1_addr Tff7b72= Tff7b72selfTff7b72.Td2a8ffEFUSE_BASE Tff7b72+ T79c0ff0x044
Te6edf3word3 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3block1_addr Tff7b72+ Tb4b4b4(T79c0ff4 Tff7b72* Te6edf3num_wordTb4b4b4)Tb4b4b4)
Te6edf3pkg_version Tff7b72= Tb4b4b4(Te6edf3word3 Tff7b72>> T79c0ff21Tb4b4b4) Tff7b72& T79c0ff0x0F
Tff7b72return Te6edf3pkg_version

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3chip_name Tff7b72= Tb4b4b4{
T79c0ff0Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-S2Ta5d6ff"Tb4b4b4,
T79c0ff1Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-S2FH16Ta5d6ff"Tb4b4b4,
T79c0ff2Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-S2FH32Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tff7b72.Td2a8ffgetTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_pkg_versionTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffunknown ESP32-S2Ta5d6ff"Tb4b4b4)

Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3chip_nameTb4b4b4)

Tff7b72def Td2a8ffget_chip_featuresTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3features Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffWiFiTa5d6ff"Tb4b4b4]

Tff7b72if Tff7b72selfTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffSecure Download Mode EnabledTa5d6ff"Tb4b4b4]

Te6edf3pkg_version Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_pkg_versionTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3pkg_version Tff7b72in Tb4b4b4[T79c0ff1Tb4b4b4, T79c0ff2Tb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3pkg_version Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffEmbedded 2MB FlashTa5d6ff"Tb4b4b4]
Tff7b72elif Te6edf3pkg_version Tff7b72== T79c0ff2Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffEmbedded 4MB FlashTa5d6ff"Tb4b4b4]
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ff105C temp ratingTa5d6ff"Tb4b4b4]

Te6edf3num_word Tff7b72= T79c0ff4
Te6edf3block2_addr Tff7b72= Tff7b72selfTff7b72.Td2a8ffEFUSE_BASE Tff7b72+ T79c0ff0x05C
Te6edf3word4 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3block2_addr Tff7b72+ Tb4b4b4(T79c0ff4 Tff7b72* Te6edf3num_wordTb4b4b4)Tb4b4b4)
Te6edf3block2_version Tff7b72= Tb4b4b4(Te6edf3word4 Tff7b72>> T79c0ff4Tb4b4b4) Tff7b72& T79c0ff0x07

Tff7b72if Te6edf3block2_version Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3features Tff7b72+Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffADC and temperature sensor calibration in BLK2 of efuseTa5d6ff"Tb4b4b4]
Tff7b72return Te6edf3features

Tff7b72def Td2a8ffget_crystal_freqTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# ESP32-S2 XTAL is fixed to 40MHz
Tff7b72return T79c0ff40

Tff7b72def Td2a8ffoverride_vddsdioTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_voltageTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3NotImplementedInROMErrorTb4b4b4(Ta5d6ff"Ta5d6ffVDD_SDIO overrides are not supported for ESP32-S2Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffread_macTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3mac0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMAC_EFUSE_REGTb4b4b4)
Te6edf3mac1 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMAC_EFUSE_REG Tff7b72+ T79c0ff4Tb4b4b4) T8b949e# only bottom 16 bits are MAC
Te6edf3bitstring Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff>IITa5d6ff"Tb4b4b4, Te6edf3mac1Tb4b4b4, Te6edf3mac0Tb4b4b4)Tb4b4b4[T79c0ff2Tb4b4b4:Tb4b4b4]
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657tupleTb4b4b4(Tffa657ordTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Te6edf3bitstringTb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4: T8b949e# Python 3, bitstring elements are already bytes
Tff7b72return Tffa657tupleTb4b4b4(Te6edf3bitstringTb4b4b4)

Tff7b72def Td2a8ffget_flash_crypt_configTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None T8b949e# doesn't exist on ESP32-S2

Tff7b72def Td2a8ffget_key_block_purposeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3key_blockTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3key_block Tff7b72< T79c0ff0 Tff7b72or Te6edf3key_block Tff7b72> T79c0ff5Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffValid key block numbers must be in range 0-5Ta5d6ff"Tb4b4b4)

Te6edf3regTb4b4b4, Te6edf3shift Tff7b72= Tb4b4b4[Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY0_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY0_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY1_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY1_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY2_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY2_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY3_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY3_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY4_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY4_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY5_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY5_SHIFTTb4b4b4)Tb4b4b4]Tb4b4b4[Te6edf3key_blockTb4b4b4]
Tff7b72return Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3regTb4b4b4) Tff7b72>> Te6edf3shiftTb4b4b4) Tff7b72& T79c0ff0xF

Tff7b72def Td2a8ffis_flash_encryption_key_validTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Need to see either an AES-128 key or two AES-256 keys
Te6edf3purposes Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffget_key_block_purposeTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Tffa657rangeTb4b4b4(T79c0ff6Tb4b4b4)Tb4b4b4]

Tff7b72if Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES128_KEY Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True

Tff7b72return Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES256_KEY_1 Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4) \
Tff7b72and Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES256_KEY_2 Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4)

Tff7b72def Td2a8ffuses_usbTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3_cacheTff7b72=Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Tff7b72return Tff7b72False T8b949e# can't detect native USB in secure download mode
Tff7b72if Tff7b72not Te6edf3_cacheTb4b4b4:
Te6edf3buf_no Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffUARTDEV_BUF_NOTb4b4b4) Tff7b72& T79c0ff0xff
Te6edf3_cacheTff7b72.Td2a8ffappendTb4b4b4(Te6edf3buf_no Tff7b72== Tff7b72selfTff7b72.Td2a8ffUARTDEV_BUF_NO_USBTb4b4b4)
Tff7b72return Te6edf3_cacheTb4b4b4[T79c0ff0Tb4b4b4]

Tff7b72def Td2a8ff_post_connectTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffuses_usbTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCK Tff7b72= Tff7b72selfTff7b72.Td2a8ffUSB_RAM_BLOCK

Tff7b72def Td2a8ff_check_if_can_resetTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
Check the strapping register to see if we can reset out of download mode.
"""
Tff7b72if Te6edf3osTff7b72.Td2a8ffgetenvTb4b4b4(Ta5d6ff"Ta5d6ffESPTOOL_TESTINGTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffESPTOOL_TESTING is set, ignoring strapping mode checkTa5d6ff"Tb4b4b4)
T8b949e# Esptool tests over USB CDC run with GPIO0 strapped low, don't complain in this case.
Tff7b72return
Te6edf3strap_reg Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffGPIO_STRAP_REGTb4b4b4)
Te6edf3force_dl_reg Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffRTC_CNTL_OPTION1_REGTb4b4b4)
Tff7b72if Te6edf3strap_reg Tff7b72& Tff7b72selfTff7b72.Td2a8ffGPIO_STRAP_SPI_BOOT_MASK Tff7b72== T79c0ff0 Tff7b72and Te6edf3force_dl_reg Tff7b72& Tff7b72selfTff7b72.Td2a8ffRTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK Tff7b72== T79c0ff0Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffERROR: Tffd700{}Ta5d6ff chip was placed into download mode using GPIO0.Tffea00\nTa5d6ff"
Ta5d6ff"Ta5d6ffesptool.py can not exit the download mode over USB. Ta5d6ff"
Ta5d6ff"Ta5d6ffTo run the app, reset the chip manually.Tffea00\nTa5d6ff"
Ta5d6ff"Ta5d6ffTo suppress this error, set --after option to Ta5d6ff'Ta5d6ffno_resetTa5d6ff'Ta5d6ff.Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_chip_descriptionTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72raise Tf85149SystemExitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72def Td2a8ffhard_resetTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffuses_usbTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_check_if_can_resetTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# EN->LOW
Tff7b72if Tff7b72selfTff7b72.Td2a8ffuses_usbTb4b4b4(Tb4b4b4)Tb4b4b4:
T8b949e# Give the chip some time to come out of reset, to be able to handle further DTR/RTS transitions
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.2Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.2Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_setRTSTb4b4b4(Tff7b72FalseTb4b4b4)


Tff7b72class T56d364ESP32S3ROMTb4b4b4(Te6edf3ESP32ROMTb4b4b4)Tb4b4b4:
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32-S3Ta5d6ff"

Te6edf3IROM_MAP_START Tff7b72= T79c0ff0x42000000
Te6edf3IROM_MAP_END Tff7b72= T79c0ff0x44000000
Te6edf3DROM_MAP_START Tff7b72= T79c0ff0x3c000000
Te6edf3DROM_MAP_END Tff7b72= T79c0ff0x3e000000

Te6edf3UART_DATE_REG_ADDR Tff7b72= T79c0ff0x60000080

Te6edf3SPI_REG_BASE Tff7b72= T79c0ff0x60002000
Te6edf3SPI_USR_OFFS Tff7b72= T79c0ff0x18
Te6edf3SPI_USR1_OFFS Tff7b72= T79c0ff0x1c
Te6edf3SPI_USR2_OFFS Tff7b72= T79c0ff0x20
Te6edf3SPI_MOSI_DLEN_OFFS Tff7b72= T79c0ff0x24
Te6edf3SPI_MISO_DLEN_OFFS Tff7b72= T79c0ff0x28
Te6edf3SPI_W0_OFFS Tff7b72= T79c0ff0x58

Te6edf3FLASH_ENCRYPTED_WRITE_ALIGN Tff7b72= T79c0ff16

T8b949e# todo: use espefuse APIs to get this info
Te6edf3EFUSE_BASE Tff7b72= T79c0ff0x6001A000 T8b949e# BLOCK0 read base address
Te6edf3MAC_EFUSE_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x044

Te6edf3EFUSE_RD_REG_BASE Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x030 T8b949e# BLOCK0 read base address

Te6edf3EFUSE_PURPOSE_KEY0_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x34
Te6edf3EFUSE_PURPOSE_KEY0_SHIFT Tff7b72= T79c0ff24
Te6edf3EFUSE_PURPOSE_KEY1_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x34
Te6edf3EFUSE_PURPOSE_KEY1_SHIFT Tff7b72= T79c0ff28
Te6edf3EFUSE_PURPOSE_KEY2_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY2_SHIFT Tff7b72= T79c0ff0
Te6edf3EFUSE_PURPOSE_KEY3_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY3_SHIFT Tff7b72= T79c0ff4
Te6edf3EFUSE_PURPOSE_KEY4_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY4_SHIFT Tff7b72= T79c0ff8
Te6edf3EFUSE_PURPOSE_KEY5_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY5_SHIFT Tff7b72= T79c0ff12

Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG Tff7b72= Te6edf3EFUSE_RD_REG_BASE
Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT Tff7b72= T79c0ff1 Tff7b72<< T79c0ff20

Te6edf3PURPOSE_VAL_XTS_AES256_KEY_1 Tff7b72= T79c0ff2
Te6edf3PURPOSE_VAL_XTS_AES256_KEY_2 Tff7b72= T79c0ff3
Te6edf3PURPOSE_VAL_XTS_AES128_KEY Tff7b72= T79c0ff4

Te6edf3UART_CLKDIV_REG Tff7b72= T79c0ff0x60000014

Te6edf3GPIO_STRAP_REG Tff7b72= T79c0ff0x60004038

Te6edf3MEMORY_MAP Tff7b72= Tb4b4b4[Tb4b4b4[T79c0ff0x00000000Tb4b4b4, T79c0ff0x00010000Tb4b4b4, Ta5d6ff"Ta5d6ffPADDINGTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3C000000Tb4b4b4, T79c0ff0x3D000000Tb4b4b4, Ta5d6ff"Ta5d6ffDROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3D000000Tb4b4b4, T79c0ff0x3E000000Tb4b4b4, Ta5d6ff"Ta5d6ffEXTRAM_DATATa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x600FE000Tb4b4b4, T79c0ff0x60100000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FC88000Tb4b4b4, T79c0ff0x3FD00000Tb4b4b4, Ta5d6ff"Ta5d6ffBYTE_ACCESSIBLETa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FC88000Tb4b4b4, T79c0ff0x403E2000Tb4b4b4, Ta5d6ff"Ta5d6ffMEM_INTERNALTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FC88000Tb4b4b4, T79c0ff0x3FD00000Tb4b4b4, Ta5d6ff"Ta5d6ffDRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40000000Tb4b4b4, T79c0ff0x4001A100Tb4b4b4, Ta5d6ff"Ta5d6ffIROM_MASKTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40370000Tb4b4b4, T79c0ff0x403E0000Tb4b4b4, Ta5d6ff"Ta5d6ffIRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x600FE000Tb4b4b4, T79c0ff0x60100000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_IRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x42000000Tb4b4b4, T79c0ff0x42800000Tb4b4b4, Ta5d6ff"Ta5d6ffIROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x50000000Tb4b4b4, T79c0ff0x50002000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DATATa5d6ff"Tb4b4b4]Tb4b4b4]

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffESP32-S3Ta5d6ff"

Tff7b72def Td2a8ffget_chip_featuresTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Ta5d6ff"Ta5d6ffWiFiTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffBLETa5d6ff"Tb4b4b4]

Tff7b72def Td2a8ffget_crystal_freqTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# ESP32S3 XTAL is fixed to 40MHz
Tff7b72return T79c0ff40

Tff7b72def Td2a8ffget_flash_crypt_configTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None T8b949e# doesn't exist on ESP32-S3

Tff7b72def Td2a8ffget_key_block_purposeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3key_blockTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3key_block Tff7b72< T79c0ff0 Tff7b72or Te6edf3key_block Tff7b72> T79c0ff5Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffValid key block numbers must be in range 0-5Ta5d6ff"Tb4b4b4)

Te6edf3regTb4b4b4, Te6edf3shift Tff7b72= Tb4b4b4[Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY0_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY0_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY1_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY1_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY2_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY2_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY3_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY3_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY4_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY4_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY5_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY5_SHIFTTb4b4b4)Tb4b4b4]Tb4b4b4[Te6edf3key_blockTb4b4b4]
Tff7b72return Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3regTb4b4b4) Tff7b72>> Te6edf3shiftTb4b4b4) Tff7b72& T79c0ff0xF

Tff7b72def Td2a8ffis_flash_encryption_key_validTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Need to see either an AES-128 key or two AES-256 keys
Te6edf3purposes Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffget_key_block_purposeTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Tffa657rangeTb4b4b4(T79c0ff6Tb4b4b4)Tb4b4b4]

Tff7b72if Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES128_KEY Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True

Tff7b72return Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES256_KEY_1 Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4) \
Tff7b72and Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES256_KEY_2 Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4)

Tff7b72def Td2a8ffoverride_vddsdioTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_voltageTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3NotImplementedInROMErrorTb4b4b4(Ta5d6ff"Ta5d6ffVDD_SDIO overrides are not supported for ESP32-S3Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffread_macTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3mac0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMAC_EFUSE_REGTb4b4b4)
Te6edf3mac1 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMAC_EFUSE_REG Tff7b72+ T79c0ff4Tb4b4b4) T8b949e# only bottom 16 bits are MAC
Te6edf3bitstring Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff>IITa5d6ff"Tb4b4b4, Te6edf3mac1Tb4b4b4, Te6edf3mac0Tb4b4b4)Tb4b4b4[T79c0ff2Tb4b4b4:Tb4b4b4]
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657tupleTb4b4b4(Tffa657ordTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Te6edf3bitstringTb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4: T8b949e# Python 3, bitstring elements are already bytes
Tff7b72return Tffa657tupleTb4b4b4(Te6edf3bitstringTb4b4b4)


Tff7b72class T56d364ESP32S3BETA2ROMTb4b4b4(Te6edf3ESP32S3ROMTb4b4b4)Tb4b4b4:
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32-S3(beta2)Ta5d6ff"
Te6edf3IMAGE_CHIP_ID Tff7b72= T79c0ff4

Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0xeb004136Tb4b4b4]

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffESP32-S3(beta2)Ta5d6ff"


Tff7b72class T56d364ESP32S3BETA3ROMTb4b4b4(Te6edf3ESP32S3ROMTb4b4b4)Tb4b4b4:
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32-S3(beta3)Ta5d6ff"
Te6edf3IMAGE_CHIP_ID Tff7b72= T79c0ff6

Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0x9Tb4b4b4]

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffESP32-S3(beta3)Ta5d6ff"


Tff7b72class T56d364ESP32C3ROMTb4b4b4(Te6edf3ESP32ROMTb4b4b4)Tb4b4b4:
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32-C3Ta5d6ff"
Te6edf3IMAGE_CHIP_ID Tff7b72= T79c0ff5

Te6edf3IROM_MAP_START Tff7b72= T79c0ff0x42000000
Te6edf3IROM_MAP_END Tff7b72= T79c0ff0x42800000
Te6edf3DROM_MAP_START Tff7b72= T79c0ff0x3c000000
Te6edf3DROM_MAP_END Tff7b72= T79c0ff0x3c800000

Te6edf3SPI_REG_BASE Tff7b72= T79c0ff0x60002000
Te6edf3SPI_USR_OFFS Tff7b72= T79c0ff0x18
Te6edf3SPI_USR1_OFFS Tff7b72= T79c0ff0x1C
Te6edf3SPI_USR2_OFFS Tff7b72= T79c0ff0x20
Te6edf3SPI_MOSI_DLEN_OFFS Tff7b72= T79c0ff0x24
Te6edf3SPI_MISO_DLEN_OFFS Tff7b72= T79c0ff0x28
Te6edf3SPI_W0_OFFS Tff7b72= T79c0ff0x58

Te6edf3BOOTLOADER_FLASH_OFFSET Tff7b72= T79c0ff0x0

T8b949e# Magic value for ESP32C3 eco 1+2 and ESP32C3 eco3 respectivly
Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0x6921506fTb4b4b4, T79c0ff0x1b31506fTb4b4b4]

Te6edf3UART_DATE_REG_ADDR Tff7b72= T79c0ff0x60000000 Tff7b72+ T79c0ff0x7c

Te6edf3EFUSE_BASE Tff7b72= T79c0ff0x60008800
Te6edf3MAC_EFUSE_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x044

Te6edf3EFUSE_RD_REG_BASE Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x030 T8b949e# BLOCK0 read base address

Te6edf3EFUSE_PURPOSE_KEY0_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x34
Te6edf3EFUSE_PURPOSE_KEY0_SHIFT Tff7b72= T79c0ff24
Te6edf3EFUSE_PURPOSE_KEY1_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x34
Te6edf3EFUSE_PURPOSE_KEY1_SHIFT Tff7b72= T79c0ff28
Te6edf3EFUSE_PURPOSE_KEY2_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY2_SHIFT Tff7b72= T79c0ff0
Te6edf3EFUSE_PURPOSE_KEY3_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY3_SHIFT Tff7b72= T79c0ff4
Te6edf3EFUSE_PURPOSE_KEY4_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY4_SHIFT Tff7b72= T79c0ff8
Te6edf3EFUSE_PURPOSE_KEY5_REG Tff7b72= Te6edf3EFUSE_BASE Tff7b72+ T79c0ff0x38
Te6edf3EFUSE_PURPOSE_KEY5_SHIFT Tff7b72= T79c0ff12

Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG Tff7b72= Te6edf3EFUSE_RD_REG_BASE
Te6edf3EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT Tff7b72= T79c0ff1 Tff7b72<< T79c0ff20

Te6edf3PURPOSE_VAL_XTS_AES128_KEY Tff7b72= T79c0ff4

Te6edf3GPIO_STRAP_REG Tff7b72= T79c0ff0x3f404038

Te6edf3FLASH_ENCRYPTED_WRITE_ALIGN Tff7b72= T79c0ff16

Te6edf3MEMORY_MAP Tff7b72= Tb4b4b4[Tb4b4b4[T79c0ff0x00000000Tb4b4b4, T79c0ff0x00010000Tb4b4b4, Ta5d6ff"Ta5d6ffPADDINGTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3C000000Tb4b4b4, T79c0ff0x3C800000Tb4b4b4, Ta5d6ff"Ta5d6ffDROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FC80000Tb4b4b4, T79c0ff0x3FCE0000Tb4b4b4, Ta5d6ff"Ta5d6ffDRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FC88000Tb4b4b4, T79c0ff0x3FD00000Tb4b4b4, Ta5d6ff"Ta5d6ffBYTE_ACCESSIBLETa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x3FF00000Tb4b4b4, T79c0ff0x3FF20000Tb4b4b4, Ta5d6ff"Ta5d6ffDROM_MASKTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x40000000Tb4b4b4, T79c0ff0x40060000Tb4b4b4, Ta5d6ff"Ta5d6ffIROM_MASKTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x42000000Tb4b4b4, T79c0ff0x42800000Tb4b4b4, Ta5d6ff"Ta5d6ffIROMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x4037C000Tb4b4b4, T79c0ff0x403E0000Tb4b4b4, Ta5d6ff"Ta5d6ffIRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x50000000Tb4b4b4, T79c0ff0x50002000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_IRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x50000000Tb4b4b4, T79c0ff0x50002000Tb4b4b4, Ta5d6ff"Ta5d6ffRTC_DRAMTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4[T79c0ff0x600FE000Tb4b4b4, T79c0ff0x60100000Tb4b4b4, Ta5d6ff"Ta5d6ffMEM_INTERNAL2Ta5d6ff"Tb4b4b4]Tb4b4b4]

Tff7b72def Td2a8ffget_pkg_versionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3num_word Tff7b72= T79c0ff3
Te6edf3block1_addr Tff7b72= Tff7b72selfTff7b72.Td2a8ffEFUSE_BASE Tff7b72+ T79c0ff0x044
Te6edf3word3 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3block1_addr Tff7b72+ Tb4b4b4(T79c0ff4 Tff7b72* Te6edf3num_wordTb4b4b4)Tb4b4b4)
Te6edf3pkg_version Tff7b72= Tb4b4b4(Te6edf3word3 Tff7b72>> T79c0ff21Tb4b4b4) Tff7b72& T79c0ff0x0F
Tff7b72return Te6edf3pkg_version

Tff7b72def Td2a8ffget_chip_revisionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# reads WAFER_VERSION field from EFUSE_RD_MAC_SPI_SYS_3_REG
Te6edf3block1_addr Tff7b72= Tff7b72selfTff7b72.Td2a8ffEFUSE_BASE Tff7b72+ T79c0ff0x044
Te6edf3num_word Tff7b72= T79c0ff3
Te6edf3pos Tff7b72= T79c0ff18
Tff7b72return Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3block1_addr Tff7b72+ Tb4b4b4(T79c0ff4 Tff7b72* Te6edf3num_wordTb4b4b4)Tb4b4b4) Tff7b72& Tb4b4b4(T79c0ff0x7 Tff7b72<< Te6edf3posTb4b4b4)Tb4b4b4) Tff7b72>> Te6edf3pos

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3chip_name Tff7b72= Tb4b4b4{
T79c0ff0Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-C3Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tff7b72.Td2a8ffgetTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_pkg_versionTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffunknown ESP32-C3Ta5d6ff"Tb4b4b4)
Te6edf3chip_revision Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_chip_revisionTb4b4b4(Tb4b4b4)

Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff (revision Tffd700%dTa5d6ff)Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3chip_nameTb4b4b4, Te6edf3chip_revisionTb4b4b4)

Tff7b72def Td2a8ffget_chip_featuresTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Ta5d6ff"Ta5d6ffWi-FiTa5d6ff"Tb4b4b4]

Tff7b72def Td2a8ffget_crystal_freqTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# ESP32C3 XTAL is fixed to 40MHz
Tff7b72return T79c0ff40

Tff7b72def Td2a8ffoverride_vddsdioTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_voltageTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3NotImplementedInROMErrorTb4b4b4(Ta5d6ff"Ta5d6ffVDD_SDIO overrides are not supported for ESP32-C3Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffread_macTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3mac0 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMAC_EFUSE_REGTb4b4b4)
Te6edf3mac1 Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Tff7b72selfTff7b72.Td2a8ffMAC_EFUSE_REG Tff7b72+ T79c0ff4Tb4b4b4) T8b949e# only bottom 16 bits are MAC
Te6edf3bitstring Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ff>IITa5d6ff"Tb4b4b4, Te6edf3mac1Tb4b4b4, Te6edf3mac0Tb4b4b4)Tb4b4b4[T79c0ff2Tb4b4b4:Tb4b4b4]
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657tupleTb4b4b4(Tffa657ordTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Te6edf3bitstringTb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4: T8b949e# Python 3, bitstring elements are already bytes
Tff7b72return Tffa657tupleTb4b4b4(Te6edf3bitstringTb4b4b4)

Tff7b72def Td2a8ffget_flash_crypt_configTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None T8b949e# doesn't exist on ESP32-C3

Tff7b72def Td2a8ffget_key_block_purposeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3key_blockTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3key_block Tff7b72< T79c0ff0 Tff7b72or Te6edf3key_block Tff7b72> T79c0ff5Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffValid key block numbers must be in range 0-5Ta5d6ff"Tb4b4b4)

Te6edf3regTb4b4b4, Te6edf3shift Tff7b72= Tb4b4b4[Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY0_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY0_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY1_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY1_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY2_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY2_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY3_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY3_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY4_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY4_SHIFTTb4b4b4)Tb4b4b4,
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY5_REGTb4b4b4, Tff7b72selfTff7b72.Td2a8ffEFUSE_PURPOSE_KEY5_SHIFTTb4b4b4)Tb4b4b4]Tb4b4b4[Te6edf3key_blockTb4b4b4]
Tff7b72return Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3regTb4b4b4) Tff7b72>> Te6edf3shiftTb4b4b4) Tff7b72& T79c0ff0xF

Tff7b72def Td2a8ffis_flash_encryption_key_validTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Need to see an AES-128 key
Te6edf3purposes Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffget_key_block_purposeTb4b4b4(Te6edf3bTb4b4b4) Tff7b72for Te6edf3b Tff7b72in Tffa657rangeTb4b4b4(T79c0ff6Tb4b4b4)Tb4b4b4]

Tff7b72return Tffa657anyTb4b4b4(Te6edf3p Tff7b72== Tff7b72selfTff7b72.Td2a8ffPURPOSE_VAL_XTS_AES128_KEY Tff7b72for Te6edf3p Tff7b72in Te6edf3purposesTb4b4b4)


Tff7b72class T56d364ESP32C6BETAROMTb4b4b4(Te6edf3ESP32C3ROMTb4b4b4)Tb4b4b4:
Te6edf3CHIP_NAME Tff7b72= Ta5d6ff"Ta5d6ffESP32-C6 BETATa5d6ff"
Te6edf3IMAGE_CHIP_ID Tff7b72= T79c0ff7

Te6edf3CHIP_DETECT_MAGIC_VALUE Tff7b72= Tb4b4b4[T79c0ff0x0da1806fTb4b4b4]

Te6edf3UART_DATE_REG_ADDR Tff7b72= T79c0ff0x00000500

Tff7b72def Td2a8ffget_chip_descriptionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3chip_name Tff7b72= Tb4b4b4{
T79c0ff0Tb4b4b4: Ta5d6ff"Ta5d6ffESP32-C6Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tff7b72.Td2a8ffgetTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_pkg_versionTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffunknown ESP32-C6Ta5d6ff"Tb4b4b4)
Te6edf3chip_revision Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_chip_revisionTb4b4b4(Tb4b4b4)

Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff (revision Tffd700%dTa5d6ff)Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3chip_nameTb4b4b4, Te6edf3chip_revisionTb4b4b4)


Tff7b72class T56d364ESP32StubLoaderTb4b4b4(Te6edf3ESP32ROMTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP32 stub loader, runs on top of ROM.
"""
Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x4000 T8b949e# matches MAX_WRITE_BLOCK in stub_loader.c
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff2 T8b949e# same as ESP8266, different to ESP32 ROM
Te6edf3IS_STUB Tff7b72= Tff7b72True

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rom_loaderTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ffsecure_download_mode
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_port
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_trace_enabled
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# resets _slip_reader


Te6edf3ESP32ROMTff7b72.Td2a8ffSTUB_CLASS Tff7b72= Te6edf3ESP32StubLoader


Tff7b72class T56d364ESP32S2StubLoaderTb4b4b4(Te6edf3ESP32S2ROMTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP32-S2 stub loader, runs on top of ROM.

(Basically the same as ESP32StubLoader, but different base class.
Can possibly be made into a mixin.)
"""
Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x4000 T8b949e# matches MAX_WRITE_BLOCK in stub_loader.c
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff2 T8b949e# same as ESP8266, different to ESP32 ROM
Te6edf3IS_STUB Tff7b72= Tff7b72True

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rom_loaderTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ffsecure_download_mode
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_port
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_trace_enabled
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# resets _slip_reader

Tff7b72if Te6edf3rom_loaderTff7b72.Td2a8ffuses_usbTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffESP_RAM_BLOCK Tff7b72= Tff7b72selfTff7b72.Td2a8ffUSB_RAM_BLOCK
Tff7b72selfTff7b72.Td2a8ffFLASH_WRITE_SIZE Tff7b72= Tff7b72selfTff7b72.Td2a8ffUSB_RAM_BLOCK


Te6edf3ESP32S2ROMTff7b72.Td2a8ffSTUB_CLASS Tff7b72= Te6edf3ESP32S2StubLoader


Tff7b72class T56d364ESP32S3BETA2StubLoaderTb4b4b4(Te6edf3ESP32S3BETA2ROMTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP32S3 stub loader, runs on top of ROM.

(Basically the same as ESP32StubLoader, but different base class.
Can possibly be made into a mixin.)
"""
Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x4000 T8b949e# matches MAX_WRITE_BLOCK in stub_loader.c
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff2 T8b949e# same as ESP8266, different to ESP32 ROM
Te6edf3IS_STUB Tff7b72= Tff7b72True

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rom_loaderTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ffsecure_download_mode
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_port
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_trace_enabled
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# resets _slip_reader


Te6edf3ESP32S3BETA2ROMTff7b72.Td2a8ffSTUB_CLASS Tff7b72= Te6edf3ESP32S3BETA2StubLoader


Tff7b72class T56d364ESP32S3BETA3StubLoaderTb4b4b4(Te6edf3ESP32S3BETA3ROMTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP32S3 stub loader, runs on top of ROM.

(Basically the same as ESP32StubLoader, but different base class.
Can possibly be made into a mixin.)
"""
Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x4000 T8b949e# matches MAX_WRITE_BLOCK in stub_loader.c
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff2 T8b949e# same as ESP8266, different to ESP32 ROM
Te6edf3IS_STUB Tff7b72= Tff7b72True

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rom_loaderTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ffsecure_download_mode
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_port
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_trace_enabled
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# resets _slip_reader


Te6edf3ESP32S3BETA3ROMTff7b72.Td2a8ffSTUB_CLASS Tff7b72= Te6edf3ESP32S3BETA3StubLoader


Tff7b72class T56d364ESP32C3StubLoaderTb4b4b4(Te6edf3ESP32C3ROMTb4b4b4)Tb4b4b4:
T8b949e""" Access class for ESP32C3 stub loader, runs on top of ROM.

(Basically the same as ESP32StubLoader, but different base class.
Can possibly be made into a mixin.)
"""
Te6edf3FLASH_WRITE_SIZE Tff7b72= T79c0ff0x4000 T8b949e# matches MAX_WRITE_BLOCK in stub_loader.c
Te6edf3STATUS_BYTES_LENGTH Tff7b72= T79c0ff2 T8b949e# same as ESP8266, different to ESP32 ROM
Te6edf3IS_STUB Tff7b72= Tff7b72True

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rom_loaderTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsecure_download_mode Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ffsecure_download_mode
Tff7b72selfTff7b72.Td2a8ff_port Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_port
Tff7b72selfTff7b72.Td2a8ff_trace_enabled Tff7b72= Te6edf3rom_loaderTff7b72.Td2a8ff_trace_enabled
Tff7b72selfTff7b72.Td2a8ffflush_inputTb4b4b4(Tb4b4b4) T8b949e# resets _slip_reader


Te6edf3ESP32C3ROMTff7b72.Td2a8ffSTUB_CLASS Tff7b72= Te6edf3ESP32C3StubLoader


Tff7b72class T56d364ESPBOOTLOADERTb4b4b4(Tffa657objectTb4b4b4)Tb4b4b4:
T8b949e""" These are constants related to software ESP8266 bootloader, working with 'v2' image files """

T8b949e# First byte of the "v2" application image
Te6edf3IMAGE_V2_MAGIC Tff7b72= T79c0ff0xea

T8b949e# First 'segment' value in a "v2" application image, appears to be a constant version value?
Te6edf3IMAGE_V2_SEGMENT Tff7b72= T79c0ff4


Tff7b72def Td2a8ffLoadFirmwareImageTb4b4b4(Te6edf3chipTb4b4b4, Te6edf3filenameTb4b4b4)Tb4b4b4:
T8b949e""" Load a firmware image. Can be for any supported SoC.

ESP8266 images will be examined to determine if they are original ROM firmware images (ESP8266ROMFirmwareImage)
or "v2" OTA bootloader images.

Returns a BaseFirmwareImage subclass, either ESP8266ROMFirmwareImage (v1) or ESP8266V2FirmwareImage (v2).
"""
Te6edf3chip Tff7b72= Te6edf3chipTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ff-Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3filenameTb4b4b4, Ta5d6ff'Ta5d6ffrbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72if Te6edf3chip Tff7b72== Ta5d6ff'Ta5d6ffesp32Ta5d6ff'Tb4b4b4:
Tff7b72return Te6edf3ESP32FirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elif Te6edf3chip Tff7b72== Ta5d6ff"Ta5d6ffesp32s2Ta5d6ff"Tb4b4b4:
Tff7b72return Te6edf3ESP32S2FirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elif Te6edf3chip Tff7b72== Ta5d6ff"Ta5d6ffesp32s3beta2Ta5d6ff"Tb4b4b4:
Tff7b72return Te6edf3ESP32S3BETA2FirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elif Te6edf3chip Tff7b72== Ta5d6ff"Ta5d6ffesp32s3beta3Ta5d6ff"Tb4b4b4:
Tff7b72return Te6edf3ESP32S3BETA3FirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elif Te6edf3chip Tff7b72== Ta5d6ff'Ta5d6ffesp32c3Ta5d6ff'Tb4b4b4:
Tff7b72return Te6edf3ESP32C3FirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elif Te6edf3chip Tff7b72== Ta5d6ff'Ta5d6ffesp32c6betaTa5d6ff'Tb4b4b4:
Tff7b72return Te6edf3ESP32C6BETAFirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elseTb4b4b4: T8b949e# Otherwise, ESP8266 so look at magic to determine the image type
Te6edf3magic Tff7b72= Tffa657ordTb4b4b4(Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72if Te6edf3magic Tff7b72== Te6edf3ESPLoaderTff7b72.Td2a8ffESP_IMAGE_MAGICTb4b4b4:
Tff7b72return Te6edf3ESP8266ROMFirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elif Te6edf3magic Tff7b72== Te6edf3ESPBOOTLOADERTff7b72.Td2a8ffIMAGE_V2_MAGICTb4b4b4:
Tff7b72return Te6edf3ESP8266V2FirmwareImageTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid image magic number: Tffd700%dTa5d6ff" Tff7b72% Te6edf3magicTb4b4b4)


Tff7b72class T56d364ImageSegmentTb4b4b4(Tffa657objectTb4b4b4)Tb4b4b4:
T8b949e""" Wrapper class for a segment in an ESP image
(very similar to a section in an ELFImage also) """
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3file_offsTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffaddr Tff7b72= Te6edf3addr
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Te6edf3data
Tff7b72selfTff7b72.Td2a8fffile_offs Tff7b72= Te6edf3file_offs
Tff7b72selfTff7b72.Td2a8ffinclude_in_checksum Tff7b72= Tff7b72True
Tff7b72if Tff7b72selfTff7b72.Td2a8ffaddr Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpad_to_alignmentTb4b4b4(T79c0ff4Tb4b4b4) T8b949e# pad all "real" ImageSegments 4 byte aligned length

Tff7b72def Td2a8ffcopy_with_new_addrTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3new_addrTb4b4b4)Tb4b4b4:
T8b949e""" Return a new ImageSegment with same data, but mapped at
a new address. """
Tff7b72return Te6edf3ImageSegmentTb4b4b4(Te6edf3new_addrTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4, T79c0ff0Tb4b4b4)

Tff7b72def Td2a8ffsplit_imageTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3split_lenTb4b4b4)Tb4b4b4:
T8b949e""" Return a new ImageSegment which splits "split_len" bytes
from the beginning of the data. Remaining bytes are kept in
this segment object (and the start address is adjusted to match.) """
Te6edf3result Tff7b72= Te6edf3copyTff7b72.Td2a8ffcopyTb4b4b4(Tff7b72selfTb4b4b4)
Te6edf3resultTff7b72.Td2a8ffdata Tff7b72= Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4[Tb4b4b4:Te6edf3split_lenTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4[Te6edf3split_lenTb4b4b4:Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffaddr Tff7b72+Tff7b72= Te6edf3split_len
Tff7b72selfTff7b72.Td2a8fffile_offs Tff7b72= Tff7b72None
Te6edf3resultTff7b72.Td2a8fffile_offs Tff7b72= Tff7b72None
Tff7b72return Te6edf3result

Tff7b72def Tff7b72__repr__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3r Tff7b72= Ta5d6ff"Ta5d6fflen 0xTffd700%05xTa5d6ff load 0xTffd700%08xTa5d6ff" Tff7b72% Tb4b4b4(Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4)Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffaddrTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8fffile_offs Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3r Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff file_offs 0xTffd700%08xTa5d6ff" Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8fffile_offsTb4b4b4)
Tff7b72return Te6edf3r

Tff7b72def Td2a8ffget_memory_typeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3imageTb4b4b4)Tb4b4b4:
T8b949e"""
Return a list describing the memory type(s) that is covered by this
segment's start address.
"""
Tff7b72return Tb4b4b4[Te6edf3map_rangeTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72for Te6edf3map_range Tff7b72in Te6edf3imageTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffMEMORY_MAP Tff7b72if Te6edf3map_rangeTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72= Tff7b72selfTff7b72.Td2a8ffaddr Tff7b72< Te6edf3map_rangeTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4]

Tff7b72def Td2a8ffpad_to_alignmentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3alignmentTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdata Tff7b72= Te6edf3pad_toTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdataTb4b4b4, Te6edf3alignmentTb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff'Tb4b4b4)


Tff7b72class T56d364ELFSectionTb4b4b4(Te6edf3ImageSegmentTb4b4b4)Tb4b4b4:
T8b949e""" Wrapper class for a section in an ELF image, has a section
name as well as the common properties of an ImageSegment. """
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Te6edf3ELFSectionTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Te6edf3addrTb4b4b4, Te6edf3dataTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffname Tff7b72= Te6edf3nameTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)

Tff7b72def Tff7b72__repr__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4, Tffa657superTb4b4b4(Te6edf3ELFSectionTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__repr__Tb4b4b4(Tb4b4b4)Tb4b4b4)


Tff7b72class T56d364BaseFirmwareImageTb4b4b4(Tffa657objectTb4b4b4)Tb4b4b4:
Te6edf3SEG_HEADER_LEN Tff7b72= T79c0ff8
Te6edf3SHA256_DIGEST_LEN Tff7b72= T79c0ff32

T8b949e""" Base class with common firmware image functions """
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsegments Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffentrypoint Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffelf_sha256 Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffelf_sha256_offset Tff7b72= T79c0ff0

Tff7b72def Td2a8ffload_common_headerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3load_fileTb4b4b4, Te6edf3expected_magicTb4b4b4)Tb4b4b4:
Tb4b4b4(Te6edf3magicTb4b4b4, Te6edf3segmentsTb4b4b4, Tff7b72selfTff7b72.Td2a8ffflash_modeTb4b4b4, Tff7b72selfTff7b72.Td2a8ffflash_size_freqTb4b4b4, Tff7b72selfTff7b72.Td2a8ffentrypointTb4b4b4) Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff'Ta5d6ff<BBBBITa5d6ff'Tb4b4b4, Te6edf3load_fileTff7b72.Td2a8ffreadTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4)

Tff7b72if Te6edf3magic Tff7b72!= Te6edf3expected_magicTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffInvalid firmware image magic=0xTffd700%xTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3magicTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3segments

Tff7b72def Td2a8ffverifyTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4) Tff7b72> T79c0ff16Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffInvalid segment count Tffd700%dTa5d6ff (max 16). Usually this indicates a linker script problem.Ta5d6ff' Tff7b72% Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffload_segmentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3is_irom_segmentTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
T8b949e""" Load the next segment from the image file """
Te6edf3file_offs Tff7b72= Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)
Tb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4) Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff'Ta5d6ff<IITa5d6ff'Tb4b4b4, Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwarn_if_unusual_segmentTb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3is_irom_segmentTb4b4b4)
Te6edf3segment_data Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3sizeTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3segment_dataTb4b4b4) Tff7b72< Te6edf3sizeTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffEnd of file reading segment 0xTffd700%xTa5d6ff, length Tffd700%dTa5d6ff (actual length Tffd700%dTa5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4, Tffa657lenTb4b4b4(Te6edf3segment_dataTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3segment Tff7b72= Te6edf3ImageSegmentTb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3segment_dataTb4b4b4, Te6edf3file_offsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsegmentsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3segmentTb4b4b4)
Tff7b72return Te6edf3segment

Tff7b72def Td2a8ffwarn_if_unusual_segmentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3is_irom_segmentTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3is_irom_segmentTb4b4b4:
Tff7b72if Te6edf3offset Tff7b72> T79c0ff0x40200000 Tff7b72or Te6edf3offset Tff7b72< T79c0ff0x3ffe0000 Tff7b72or Te6edf3size Tff7b72> T79c0ff65536Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: Suspicious segment 0xTffd700%xTa5d6ff, length Tffd700%dTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffmaybe_patch_segment_dataTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3segment_dataTb4b4b4)Tb4b4b4:
T8b949e"""If SHA256 digest of the ELF file needs to be inserted into this segment, do so. Returns segment data."""
Te6edf3segment_len Tff7b72= Tffa657lenTb4b4b4(Te6edf3segment_dataTb4b4b4)
Te6edf3file_pos Tff7b72= Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) T8b949e# file_pos is position in the .bin file
Tff7b72if Tff7b72selfTff7b72.Td2a8ffelf_sha256_offset Tff7b72>Tff7b72= Te6edf3file_pos Tff7b72and Tff7b72selfTff7b72.Td2a8ffelf_sha256_offset Tff7b72< Te6edf3file_pos Tff7b72+ Te6edf3segment_lenTb4b4b4:
T8b949e# SHA256 digest needs to be patched into this binary segment,
T8b949e# calculate offset of the digest inside the binary segment.
Te6edf3patch_offset Tff7b72= Tff7b72selfTff7b72.Td2a8ffelf_sha256_offset Tff7b72- Te6edf3file_pos
T8b949e# Sanity checks
Tff7b72if Te6edf3patch_offset Tff7b72< Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LEN Tff7b72or Te6edf3patch_offset Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSHA256_DIGEST_LEN Tff7b72> Te6edf3segment_lenTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffCannot place SHA256 digest on segment boundaryTa5d6ff'
Ta5d6ff'Ta5d6ff(elf_sha256_offset=Tffd700%dTa5d6ff, file_pos=Tffd700%dTa5d6ff, segment_size=Tffd700%dTa5d6ff)Ta5d6ff' Tff7b72%
Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffelf_sha256_offsetTb4b4b4, Te6edf3file_posTb4b4b4, Te6edf3segment_lenTb4b4b4)Tb4b4b4)
T8b949e# offset relative to the data part
Te6edf3patch_offset Tff7b72-Tff7b72= Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LEN
Tff7b72if Te6edf3segment_dataTb4b4b4[Te6edf3patch_offsetTb4b4b4:Te6edf3patch_offset Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSHA256_DIGEST_LENTb4b4b4] Tff7b72!= Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff' Tff7b72* Tff7b72selfTff7b72.Td2a8ffSHA256_DIGEST_LENTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffContents of segment at SHA256 digest offset 0xTffd700%xTa5d6ff are not all zero. Refusing to overwrite.Ta5d6ff' Tff7b72%
Tff7b72selfTff7b72.Td2a8ffelf_sha256_offsetTb4b4b4)
Tff7b72assertTb4b4b4(Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffelf_sha256Tb4b4b4) Tff7b72== Tff7b72selfTff7b72.Td2a8ffSHA256_DIGEST_LENTb4b4b4)
Te6edf3segment_data Tff7b72= Te6edf3segment_dataTb4b4b4[T79c0ff0Tb4b4b4:Te6edf3patch_offsetTb4b4b4] Tff7b72+ Tff7b72selfTff7b72.Td2a8ffelf_sha256 Tff7b72+ \
Te6edf3segment_dataTb4b4b4[Te6edf3patch_offset Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSHA256_DIGEST_LENTb4b4b4:Tb4b4b4]
Tff7b72return Te6edf3segment_data

Tff7b72def Td2a8ffsave_segmentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e""" Save the next segment to the image file, return next checksum value if provided """
Te6edf3segment_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffmaybe_patch_segment_dataTb4b4b4(Te6edf3fTb4b4b4, Te6edf3segmentTff7b72.Td2a8ffdataTb4b4b4)
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<IITa5d6ff'Tb4b4b4, Te6edf3segmentTff7b72.Td2a8ffaddrTb4b4b4, Tffa657lenTb4b4b4(Te6edf3segment_dataTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3segment_dataTb4b4b4)
Tff7b72if Te6edf3checksum Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3ESPLoaderTff7b72.Td2a8ffchecksumTb4b4b4(Te6edf3segment_dataTb4b4b4, Te6edf3checksumTb4b4b4)

Tff7b72def Td2a8ffread_checksumTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4)Tb4b4b4:
T8b949e""" Return ESPLoader checksum from end of just-read image """
T8b949e# Skip the padding. The checksum is stored in the last byte so that the
T8b949e# file is a multiple of 16 bytes.
Te6edf3align_file_positionTb4b4b4(Te6edf3fTb4b4b4, T79c0ff16Tb4b4b4)
Tff7b72return Tffa657ordTb4b4b4(Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffcalculate_checksumTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e""" Calculate checksum of loaded image, based on segments in
segment array.
"""
Te6edf3checksum Tff7b72= Te6edf3ESPLoaderTff7b72.Td2a8ffESP_CHECKSUM_MAGIC
Tff7b72for Te6edf3seg Tff7b72in Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4:
Tff7b72if Te6edf3segTff7b72.Td2a8ffinclude_in_checksumTb4b4b4:
Te6edf3checksum Tff7b72= Te6edf3ESPLoaderTff7b72.Td2a8ffchecksumTb4b4b4(Te6edf3segTff7b72.Td2a8ffdataTb4b4b4, Te6edf3checksumTb4b4b4)
Tff7b72return Te6edf3checksum

Tff7b72def Td2a8ffappend_checksumTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3checksumTb4b4b4)Tb4b4b4:
T8b949e""" Append ESPLoader checksum to the just-written image """
Te6edf3align_file_positionTb4b4b4(Te6edf3fTb4b4b4, T79c0ff16Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ffBTa5d6ff'Tb4b4b4, Te6edf3checksumTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffwrite_common_headerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3segmentsTb4b4b4)Tb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff'Ta5d6ff<BBBBITa5d6ff'Tb4b4b4, Te6edf3ESPLoaderTff7b72.Td2a8ffESP_IMAGE_MAGICTb4b4b4, Tffa657lenTb4b4b4(Te6edf3segmentsTb4b4b4)Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffflash_modeTb4b4b4, Tff7b72selfTff7b72.Td2a8ffflash_size_freqTb4b4b4, Tff7b72selfTff7b72.Td2a8ffentrypointTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffis_irom_addrTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4)Tb4b4b4:
T8b949e""" Returns True if an address starts in the irom region.
Valid for ESP8266 only.
"""
Tff7b72return Te6edf3ESP8266ROMTff7b72.Td2a8ffIROM_MAP_START Tff7b72<Tff7b72= Te6edf3addr Tff7b72< Te6edf3ESP8266ROMTff7b72.Td2a8ffIROM_MAP_END

Tff7b72def Td2a8ffget_irom_segmentTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3irom_segments Tff7b72= Tb4b4b4[Te6edf3s Tff7b72for Te6edf3s Tff7b72in Tff7b72selfTff7b72.Td2a8ffsegments Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_irom_addrTb4b4b4(Te6edf3sTff7b72.Td2a8ffaddrTb4b4b4)Tb4b4b4]
Tff7b72if Tffa657lenTb4b4b4(Te6edf3irom_segmentsTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3irom_segmentsTb4b4b4) Tff7b72!= T79c0ff1Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffFound Tffd700%dTa5d6ff segments that could be irom0. Bad ELF file?Ta5d6ff' Tff7b72% Tffa657lenTb4b4b4(Te6edf3irom_segmentsTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3irom_segmentsTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72return Tff7b72None

Tff7b72def Td2a8ffget_non_irom_segmentsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3irom_segment Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_irom_segmentTb4b4b4(Tb4b4b4)
Tff7b72return Tb4b4b4[Te6edf3s Tff7b72for Te6edf3s Tff7b72in Tff7b72selfTff7b72.Td2a8ffsegments Tff7b72if Te6edf3s Tff7b72!= Te6edf3irom_segmentTb4b4b4]

Tff7b72def Td2a8ffmerge_adjacent_segmentsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4:
Tff7b72return T8b949e# nothing to merge

Te6edf3segments Tff7b72= Tb4b4b4[Tb4b4b4]
T8b949e# The easiest way to merge the sections is the browse them backward.
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4) Tff7b72- T79c0ff1Tb4b4b4, T79c0ff0Tb4b4b4, Tff7b72-T79c0ff1Tb4b4b4)Tb4b4b4:
T8b949e# elem is the previous section, the one `next_elem` may need to be
T8b949e# merged in
Te6edf3elem Tff7b72= Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4[Te6edf3i Tff7b72- T79c0ff1Tb4b4b4]
Te6edf3next_elem Tff7b72= Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4[Te6edf3iTb4b4b4]
Tff7b72if Tffa657allTb4b4b4(Tb4b4b4(Te6edf3elemTff7b72.Td2a8ffget_memory_typeTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72== Te6edf3next_elemTff7b72.Td2a8ffget_memory_typeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4,
Te6edf3elemTff7b72.Td2a8ffinclude_in_checksum Tff7b72== Te6edf3next_elemTff7b72.Td2a8ffinclude_in_checksumTb4b4b4,
Te6edf3next_elemTff7b72.Td2a8ffaddr Tff7b72== Te6edf3elemTff7b72.Td2a8ffaddr Tff7b72+ Tffa657lenTb4b4b4(Te6edf3elemTff7b72.Td2a8ffdataTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4:
T8b949e# Merge any segment that ends where the next one starts, without spanning memory types
T8b949e#
T8b949e# (don't 'pad' any gaps here as they may be excluded from the image due to 'noinit'
T8b949e# or other reasons.)
Te6edf3elemTff7b72.Td2a8ffdata Tff7b72+Tff7b72= Te6edf3next_elemTff7b72.Td2a8ffdata
Tff7b72elseTb4b4b4:
T8b949e# The section next_elem cannot be merged into the previous one,
T8b949e# which means it needs to be part of the final segments.
T8b949e# As we are browsing the list backward, the elements need to be
T8b949e# inserted at the beginning of the final list.
Te6edf3segmentsTff7b72.Td2a8ffinsertTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3next_elemTb4b4b4)

T8b949e# The first segment will always be here as it cannot be merged into any
T8b949e# "previous" section.
Te6edf3segmentsTff7b72.Td2a8ffinsertTb4b4b4(T79c0ff0Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)

T8b949e# note: we could sort segments here as well, but the ordering of segments is sometimes
T8b949e# important for other reasons (like embedded ELF SHA-256), so we assume that the linker
T8b949e# script will have produced any adjacent sections in linear order in the ELF, anyhow.
Tff7b72selfTff7b72.Td2a8ffsegments Tff7b72= Te6edf3segments


Tff7b72class T56d364ESP8266ROMFirmwareImageTb4b4b4(Te6edf3BaseFirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" 'Version 1' firmware image, segments loaded directly by the ROM bootloader. """

Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP8266ROM

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3load_fileTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Te6edf3ESP8266ROMFirmwareImageTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffflash_mode Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffflash_size_freq Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffversion Tff7b72= T79c0ff1

Tff7b72if Te6edf3load_file Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3segments Tff7b72= Tff7b72selfTff7b72.Td2a8ffload_common_headerTb4b4b4(Te6edf3load_fileTb4b4b4, Te6edf3ESPLoaderTff7b72.Td2a8ffESP_IMAGE_MAGICTb4b4b4)

Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(Te6edf3segmentsTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffload_segmentTb4b4b4(Te6edf3load_fileTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffchecksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_checksumTb4b4b4(Te6edf3load_fileTb4b4b4)

Tff7b72selfTff7b72.Td2a8ffverifyTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffdefault_output_nameTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3input_fileTb4b4b4)Tb4b4b4:
T8b949e""" Derive a default output name from the ELF name. """
Tff7b72return Te6edf3input_file Tff7b72+ Ta5d6ff'Ta5d6ff-Ta5d6ff'

Tff7b72def Td2a8ffsaveTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3basenameTb4b4b4)Tb4b4b4:
T8b949e""" Save a set of V1 images for flashing. Parameter is a base filename. """
T8b949e# IROM data goes in its own plain binary file
Te6edf3irom_segment Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_irom_segmentTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3irom_segment Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff0xTffd700%05xTa5d6ff.binTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3basenameTb4b4b4, Te6edf3irom_segmentTff7b72.Td2a8ffaddr Tff7b72- Te6edf3ESP8266ROMTff7b72.Td2a8ffIROM_MAP_STARTTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3irom_segmentTff7b72.Td2a8ffdataTb4b4b4)

T8b949e# everything but IROM goes at 0x00000 in an image file
Te6edf3normal_segments Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_non_irom_segmentsTb4b4b4(Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff0x00000.binTa5d6ff" Tff7b72% Te6edf3basenameTb4b4b4, Ta5d6ff'Ta5d6ffwbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffwrite_common_headerTb4b4b4(Te6edf3fTb4b4b4, Te6edf3normal_segmentsTb4b4b4)
Te6edf3checksum Tff7b72= Te6edf3ESPLoaderTff7b72.Td2a8ffESP_CHECKSUM_MAGIC
Tff7b72for Te6edf3segment Tff7b72in Te6edf3normal_segmentsTb4b4b4:
Te6edf3checksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffappend_checksumTb4b4b4(Te6edf3fTb4b4b4, Te6edf3checksumTb4b4b4)


Te6edf3ESP8266ROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP8266ROMFirmwareImage


Tff7b72class T56d364ESP8266V2FirmwareImageTb4b4b4(Te6edf3BaseFirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" 'Version 2' firmware image, segments loaded by software bootloader stub
(ie Espressif bootloader or rboot)
"""

Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP8266ROM

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3load_fileTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Te6edf3ESP8266V2FirmwareImageTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffversion Tff7b72= T79c0ff2
Tff7b72if Te6edf3load_file Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3segments Tff7b72= Tff7b72selfTff7b72.Td2a8ffload_common_headerTb4b4b4(Te6edf3load_fileTb4b4b4, Te6edf3ESPBOOTLOADERTff7b72.Td2a8ffIMAGE_V2_MAGICTb4b4b4)
Tff7b72if Te6edf3segments Tff7b72!= Te6edf3ESPBOOTLOADERTff7b72.Td2a8ffIMAGE_V2_SEGMENTTb4b4b4:
T8b949e# segment count is not really segment count here, but we expect to see '4'
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWarning: V2 header has unexpected Ta5d6ff"Ta5d6ffsegmentTa5d6ff"Ta5d6ff count Tffd700%dTa5d6ff (usually 4)Ta5d6ff' Tff7b72% Te6edf3segmentsTb4b4b4)

T8b949e# irom segment comes before the second header
T8b949e#
T8b949e# the file is saved in the image with a zero load address
T8b949e# in the header, so we need to calculate a load address
Te6edf3irom_segment Tff7b72= Tff7b72selfTff7b72.Td2a8ffload_segmentTb4b4b4(Te6edf3load_fileTb4b4b4, Tff7b72TrueTb4b4b4)
Te6edf3irom_segmentTff7b72.Td2a8ffaddr Tff7b72= T79c0ff0 T8b949e# for actual mapped addr, add ESP8266ROM.IROM_MAP_START + flashing_addr + 8
Te6edf3irom_segmentTff7b72.Td2a8ffinclude_in_checksum Tff7b72= Tff7b72False

Te6edf3first_flash_mode Tff7b72= Tff7b72selfTff7b72.Td2a8ffflash_mode
Te6edf3first_flash_size_freq Tff7b72= Tff7b72selfTff7b72.Td2a8ffflash_size_freq
Te6edf3first_entrypoint Tff7b72= Tff7b72selfTff7b72.Td2a8ffentrypoint
T8b949e# load the second header

Te6edf3segments Tff7b72= Tff7b72selfTff7b72.Td2a8ffload_common_headerTb4b4b4(Te6edf3load_fileTb4b4b4, Te6edf3ESPLoaderTff7b72.Td2a8ffESP_IMAGE_MAGICTb4b4b4)

Tff7b72if Te6edf3first_flash_mode Tff7b72!= Tff7b72selfTff7b72.Td2a8ffflash_modeTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: Flash mode value in first header (0xTffd700%02xTa5d6ff) disagrees with second (0xTffd700%02xTa5d6ff). Using second value.Ta5d6ff'
Tff7b72% Tb4b4b4(Te6edf3first_flash_modeTb4b4b4, Tff7b72selfTff7b72.Td2a8ffflash_modeTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3first_flash_size_freq Tff7b72!= Tff7b72selfTff7b72.Td2a8ffflash_size_freqTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: Flash size/freq value in first header (0xTffd700%02xTa5d6ff) disagrees with second (0xTffd700%02xTa5d6ff). Using second value.Ta5d6ff'
Tff7b72% Tb4b4b4(Te6edf3first_flash_size_freqTb4b4b4, Tff7b72selfTff7b72.Td2a8ffflash_size_freqTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3first_entrypoint Tff7b72!= Tff7b72selfTff7b72.Td2a8ffentrypointTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: Entrypoint address in first header (0xTffd700%08xTa5d6ff) disagrees with second header (0xTffd700%08xTa5d6ff). Using second value.Ta5d6ff'
Tff7b72% Tb4b4b4(Te6edf3first_entrypointTb4b4b4, Tff7b72selfTff7b72.Td2a8ffentrypointTb4b4b4)Tb4b4b4)

T8b949e# load all the usual segments
Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(Te6edf3segmentsTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffload_segmentTb4b4b4(Te6edf3load_fileTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffchecksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_checksumTb4b4b4(Te6edf3load_fileTb4b4b4)

Tff7b72selfTff7b72.Td2a8ffverifyTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffdefault_output_nameTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3input_fileTb4b4b4)Tb4b4b4:
T8b949e""" Derive a default output name from the ELF name. """
Te6edf3irom_segment Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_irom_segmentTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3irom_segment Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3irom_offs Tff7b72= Te6edf3irom_segmentTff7b72.Td2a8ffaddr Tff7b72- Te6edf3ESP8266ROMTff7b72.Td2a8ffIROM_MAP_START
Tff7b72elseTb4b4b4:
Te6edf3irom_offs Tff7b72= T79c0ff0
Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff-0xTffd700%05xTa5d6ff.binTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitextTb4b4b4(Te6edf3input_fileTb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4,
Te6edf3irom_offs Tff7b72& Tff7b72~Tb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72- T79c0ff1Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffsaveTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3filenameTb4b4b4)Tb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3filenameTb4b4b4, Ta5d6ff'Ta5d6ffwbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
T8b949e# Save first header for irom0 segment
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ff<BBBBITa5d6ff'Tb4b4b4, Te6edf3ESPBOOTLOADERTff7b72.Td2a8ffIMAGE_V2_MAGICTb4b4b4, Te6edf3ESPBOOTLOADERTff7b72.Td2a8ffIMAGE_V2_SEGMENTTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffflash_modeTb4b4b4, Tff7b72selfTff7b72.Td2a8ffflash_size_freqTb4b4b4, Tff7b72selfTff7b72.Td2a8ffentrypointTb4b4b4)Tb4b4b4)

Te6edf3irom_segment Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_irom_segmentTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3irom_segment Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
T8b949e# save irom0 segment, make sure it has load addr 0 in the file
Te6edf3irom_segment Tff7b72= Te6edf3irom_segmentTff7b72.Td2a8ffcopy_with_new_addrTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3irom_segmentTff7b72.Td2a8ffpad_to_alignmentTb4b4b4(T79c0ff16Tb4b4b4) T8b949e# irom_segment must end on a 16 byte boundary
Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3irom_segmentTb4b4b4)

T8b949e# second header, matches V1 header and contains loadable segments
Te6edf3normal_segments Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_non_irom_segmentsTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffwrite_common_headerTb4b4b4(Te6edf3fTb4b4b4, Te6edf3normal_segmentsTb4b4b4)
Te6edf3checksum Tff7b72= Te6edf3ESPLoaderTff7b72.Td2a8ffESP_CHECKSUM_MAGIC
Tff7b72for Te6edf3segment Tff7b72in Te6edf3normal_segmentsTb4b4b4:
Te6edf3checksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffappend_checksumTb4b4b4(Te6edf3fTb4b4b4, Te6edf3checksumTb4b4b4)

T8b949e# calculate a crc32 of entire file and append
T8b949e# (algorithm used by recent 8266 SDK bootloaders)
Tff7b72with Tffa657openTb4b4b4(Te6edf3filenameTb4b4b4, Ta5d6ff'Ta5d6ffrbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3crc Tff7b72= Te6edf3esp8266_crc32Tb4b4b4(Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3filenameTb4b4b4, Ta5d6ff'Ta5d6ffabTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Te6edf3crcTb4b4b4)Tb4b4b4)


T8b949e# Backwards compatibility for previous API, remove in esptool.py V3
Te6edf3ESPFirmwareImage Tff7b72= Te6edf3ESP8266ROMFirmwareImage
Te6edf3OTAFirmwareImage Tff7b72= Te6edf3ESP8266V2FirmwareImage


Tff7b72def Td2a8ffesp8266_crc32Tb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e"""
CRC32 algorithm used by 8266 SDK bootloader (and gen_appbin.py).
"""
Te6edf3crc Tff7b72= Te6edf3binasciiTff7b72.Td2a8ffcrc32Tb4b4b4(Te6edf3dataTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72& T79c0ff0xFFFFFFFF
Tff7b72if Te6edf3crc Tff7b72& T79c0ff0x80000000Tb4b4b4:
Tff7b72return Te6edf3crc Tff7b72^ T79c0ff0xFFFFFFFF
Tff7b72elseTb4b4b4:
Tff7b72return Te6edf3crc Tff7b72+ T79c0ff1


Tff7b72class T56d364ESP32FirmwareImageTb4b4b4(Te6edf3BaseFirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" ESP32 firmware image is very similar to V1 ESP8266 image,
except with an additional 16 byte reserved header at top of image,
and because of new flash mapping capabilities the flash-mapped regions
can be placed in the normal image (just @ 64kB padded offsets).
"""

Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP32ROM

T8b949e# ROM bootloader will read the wp_pin field if SPI flash
T8b949e# pins are remapped via flash. IDF actually enables QIO only
T8b949e# from software bootloader, so this can be ignored. But needs
T8b949e# to be set to this value so ROM bootloader will skip it.
Te6edf3WP_PIN_DISABLED Tff7b72= T79c0ff0xEE

Te6edf3EXTENDED_HEADER_STRUCT_FMT Tff7b72= Ta5d6ff"Ta5d6ff<BBBBHBTa5d6ff" Tff7b72+ Tb4b4b4(Ta5d6ff"Ta5d6ffBTa5d6ff" Tff7b72* T79c0ff8Tb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ffBTa5d6ff"

Te6edf3IROM_ALIGN Tff7b72= T79c0ff65536

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3load_fileTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Te6edf3ESP32FirmwareImageTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsecure_pad Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffflash_mode Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffflash_size_freq Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffversion Tff7b72= T79c0ff1
Tff7b72selfTff7b72.Td2a8ffwp_pin Tff7b72= Tff7b72selfTff7b72.Td2a8ffWP_PIN_DISABLED
T8b949e# SPI pin drive levels
Tff7b72selfTff7b72.Td2a8ffclk_drv Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffq_drv Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffd_drv Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffcs_drv Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffhd_drv Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffwp_drv Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffmin_rev Tff7b72= T79c0ff0

Tff7b72selfTff7b72.Td2a8ffappend_digest Tff7b72= Tff7b72True

Tff7b72if Te6edf3load_file Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3start Tff7b72= Te6edf3load_fileTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)

Te6edf3segments Tff7b72= Tff7b72selfTff7b72.Td2a8ffload_common_headerTb4b4b4(Te6edf3load_fileTb4b4b4, Te6edf3ESPLoaderTff7b72.Td2a8ffESP_IMAGE_MAGICTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffload_extended_headerTb4b4b4(Te6edf3load_fileTb4b4b4)

Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(Te6edf3segmentsTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffload_segmentTb4b4b4(Te6edf3load_fileTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffchecksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffread_checksumTb4b4b4(Te6edf3load_fileTb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffappend_digestTb4b4b4:
Te6edf3end Tff7b72= Te6edf3load_fileTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstored_digest Tff7b72= Te6edf3load_fileTff7b72.Td2a8ffreadTb4b4b4(T79c0ff32Tb4b4b4)
Te6edf3load_fileTff7b72.Td2a8ffseekTb4b4b4(Te6edf3startTb4b4b4)
Te6edf3calc_digest Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffsha256Tb4b4b4(Tb4b4b4)
Te6edf3calc_digestTff7b72.Td2a8ffupdateTb4b4b4(Te6edf3load_fileTff7b72.Td2a8ffreadTb4b4b4(Te6edf3end Tff7b72- Te6edf3startTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcalc_digest Tff7b72= Te6edf3calc_digestTff7b72.Td2a8ffdigestTb4b4b4(Tb4b4b4) T8b949e# TODO: decide what to do here?

Tff7b72selfTff7b72.Td2a8ffverifyTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffis_flash_addrTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3addrTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffIROM_MAP_START Tff7b72<Tff7b72= Te6edf3addr Tff7b72< Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffIROM_MAP_ENDTb4b4b4) \
Tff7b72or Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffDROM_MAP_START Tff7b72<Tff7b72= Te6edf3addr Tff7b72< Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffDROM_MAP_ENDTb4b4b4)

Tff7b72def Td2a8ffdefault_output_nameTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3input_fileTb4b4b4)Tb4b4b4:
T8b949e""" Derive a default output name from the ELF name. """
Tff7b72return Ta5d6ff"Tffd700%sTa5d6ff.binTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitextTb4b4b4(Te6edf3input_fileTb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)

Tff7b72def Td2a8ffwarn_if_unusual_segmentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3offsetTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3is_irom_segmentTb4b4b4)Tb4b4b4:
Tff7b72pass T8b949e# TODO: add warnings for ESP32 segment offset/size combinations that are wrong

Tff7b72def Td2a8ffsaveTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3filenameTb4b4b4)Tb4b4b4:
Te6edf3total_segments Tff7b72= T79c0ff0
Tff7b72with Te6edf3ioTff7b72.Td2a8ffBytesIOTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4: T8b949e# write file to memory first
Tff7b72selfTff7b72.Td2a8ffwrite_common_headerTb4b4b4(Te6edf3fTb4b4b4, Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4)

T8b949e# first 4 bytes of header are read by ROM bootloader for SPI
T8b949e# config, but currently unused
Tff7b72selfTff7b72.Td2a8ffsave_extended_headerTb4b4b4(Te6edf3fTb4b4b4)

Te6edf3checksum Tff7b72= Te6edf3ESPLoaderTff7b72.Td2a8ffESP_CHECKSUM_MAGIC

T8b949e# split segments into flash-mapped vs ram-loaded, and take copies so we can mutate them
Te6edf3flash_segments Tff7b72= Tb4b4b4[Te6edf3copyTff7b72.Td2a8ffdeepcopyTb4b4b4(Te6edf3sTb4b4b4) Tff7b72for Te6edf3s Tff7b72in Tffa657sortedTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3sTb4b4b4:Te6edf3sTff7b72.Td2a8ffaddrTb4b4b4) Tff7b72if Tff7b72selfTff7b72.Td2a8ffis_flash_addrTb4b4b4(Te6edf3sTff7b72.Td2a8ffaddrTb4b4b4)Tb4b4b4]
Te6edf3ram_segments Tff7b72= Tb4b4b4[Te6edf3copyTff7b72.Td2a8ffdeepcopyTb4b4b4(Te6edf3sTb4b4b4) Tff7b72for Te6edf3s Tff7b72in Tffa657sortedTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsegmentsTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3sTb4b4b4:Te6edf3sTff7b72.Td2a8ffaddrTb4b4b4) Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffis_flash_addrTb4b4b4(Te6edf3sTff7b72.Td2a8ffaddrTb4b4b4)Tb4b4b4]

T8b949e# check for multiple ELF sections that are mapped in the same flash mapping region.
T8b949e# this is usually a sign of a broken linker script, but if you have a legitimate
T8b949e# use case then let us know
Tff7b72if Tffa657lenTb4b4b4(Te6edf3flash_segmentsTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3last_addr Tff7b72= Te6edf3flash_segmentsTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffaddr
Tff7b72for Te6edf3segment Tff7b72in Te6edf3flash_segmentsTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3segmentTff7b72.Td2a8ffaddr Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN Tff7b72== Te6edf3last_addr Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffIROM_ALIGNTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffSegment loaded at 0xTffd700%08xTa5d6ff lands in same 64KB flash mapping as segment loaded at 0xTffd700%08xTa5d6ff. Ta5d6ff"
Ta5d6ff"Ta5d6ffCanTa5d6ff'Ta5d6fft generate binary. Suggest changing linker script or ELF to merge sections.Ta5d6ff"Tb4b4b4) Tff7b72%
Tb4b4b4(Te6edf3segmentTff7b72.Td2a8ffaddrTb4b4b4, Te6edf3last_addrTb4b4b4)Tb4b4b4)
Te6edf3last_addr Tff7b72= Te6edf3segmentTff7b72.Td2a8ffaddr

Tff7b72def Td2a8ffget_alignment_data_neededTb4b4b4(Te6edf3segmentTb4b4b4)Tb4b4b4:
T8b949e# Actual alignment (in data bytes) required for a segment header: positioned so that
T8b949e# after we write the next 8 byte header, file_offs % IROM_ALIGN == segment.addr % IROM_ALIGN
T8b949e#
T8b949e# (this is because the segment's vaddr may not be IROM_ALIGNed, more likely is aligned
T8b949e# IROM_ALIGN+0x18 to account for the binary file header
Te6edf3align_past Tff7b72= Tb4b4b4(Te6edf3segmentTff7b72.Td2a8ffaddr Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGNTb4b4b4) Tff7b72- Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LEN
Te6edf3pad_len Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN Tff7b72- Tb4b4b4(Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGNTb4b4b4)Tb4b4b4) Tff7b72+ Te6edf3align_past
Tff7b72if Te6edf3pad_len Tff7b72== T79c0ff0 Tff7b72or Te6edf3pad_len Tff7b72== Tff7b72selfTff7b72.Td2a8ffIROM_ALIGNTb4b4b4:
Tff7b72return T79c0ff0 T8b949e# already aligned

T8b949e# subtract SEG_HEADER_LEN a second time, as the padding block has a header as well
Te6edf3pad_len Tff7b72-Tff7b72= Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LEN
Tff7b72if Te6edf3pad_len Tff7b72< T79c0ff0Tb4b4b4:
Te6edf3pad_len Tff7b72+Tff7b72= Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN
Tff7b72return Te6edf3pad_len

T8b949e# try to fit each flash segment on a 64kB aligned boundary
T8b949e# by padding with parts of the non-flash segments...
Tff7b72while Tffa657lenTb4b4b4(Te6edf3flash_segmentsTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3segment Tff7b72= Te6edf3flash_segmentsTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3pad_len Tff7b72= Te6edf3get_alignment_data_neededTb4b4b4(Te6edf3segmentTb4b4b4)
Tff7b72if Te6edf3pad_len Tff7b72> T79c0ff0Tb4b4b4: T8b949e# need to pad
Tff7b72if Tffa657lenTb4b4b4(Te6edf3ram_segmentsTb4b4b4) Tff7b72> T79c0ff0 Tff7b72and Te6edf3pad_len Tff7b72> Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LENTb4b4b4:
Te6edf3pad_segment Tff7b72= Te6edf3ram_segmentsTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffsplit_imageTb4b4b4(Te6edf3pad_lenTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3ram_segmentsTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffdataTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3ram_segmentsTff7b72.Td2a8ffpopTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3pad_segment Tff7b72= Te6edf3ImageSegmentTb4b4b4(T79c0ff0Tb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff' Tff7b72* Te6edf3pad_lenTb4b4b4, Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3checksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3pad_segmentTb4b4b4, Te6edf3checksumTb4b4b4)
Te6edf3total_segments Tff7b72+Tff7b72= T79c0ff1
Tff7b72elseTb4b4b4:
T8b949e# write the flash segment
Tff7b72assert Tb4b4b4(Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72+ T79c0ff8Tb4b4b4) Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN Tff7b72== Te6edf3segmentTff7b72.Td2a8ffaddr Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN
Te6edf3checksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffsave_flash_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTb4b4b4)
Te6edf3flash_segmentsTff7b72.Td2a8ffpopTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3total_segments Tff7b72+Tff7b72= T79c0ff1

T8b949e# flash segments all written, so write any remaining RAM segments
Tff7b72for Te6edf3segment Tff7b72in Te6edf3ram_segmentsTb4b4b4:
Te6edf3checksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTb4b4b4)
Te6edf3total_segments Tff7b72+Tff7b72= T79c0ff1

Tff7b72if Tff7b72selfTff7b72.Td2a8ffsecure_padTb4b4b4:
T8b949e# pad the image so that after signing it will end on a a 64KB boundary.
T8b949e# This ensures all mapped flash content will be verified.
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffappend_digestTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffsecure_pad only applies if a SHA-256 digest is also appended to the imageTa5d6ff"Tb4b4b4)
Te6edf3align_past Tff7b72= Tb4b4b4(Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LENTb4b4b4) Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN
T8b949e# 16 byte aligned checksum (force the alignment to simplify calculations)
Te6edf3checksum_space Tff7b72= T79c0ff16
Tff7b72if Tff7b72selfTff7b72.Td2a8ffsecure_pad Tff7b72== Ta5d6ff'Ta5d6ff1Ta5d6ff'Tb4b4b4:
T8b949e# after checksum: SHA-256 digest + (to be added by signing process) version, signature + 12 trailing bytes due to alignment
Te6edf3space_after_checksum Tff7b72= T79c0ff32 Tff7b72+ T79c0ff4 Tff7b72+ T79c0ff64 Tff7b72+ T79c0ff12
Tff7b72elif Tff7b72selfTff7b72.Td2a8ffsecure_pad Tff7b72== Ta5d6ff'Ta5d6ff2Ta5d6ff'Tb4b4b4: T8b949e# Secure Boot V2
T8b949e# after checksum: SHA-256 digest + signature sector, but we place signature sector after the 64KB boundary
Te6edf3space_after_checksum Tff7b72= T79c0ff32
Te6edf3pad_len Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN Tff7b72- Te6edf3align_past Tff7b72- Te6edf3checksum_space Tff7b72- Te6edf3space_after_checksumTb4b4b4) Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN
Te6edf3pad_segment Tff7b72= Te6edf3ImageSegmentTb4b4b4(T79c0ff0Tb4b4b4, Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff' Tff7b72* Te6edf3pad_lenTb4b4b4, Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4)

Te6edf3checksum Tff7b72= Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3pad_segmentTb4b4b4, Te6edf3checksumTb4b4b4)
Te6edf3total_segments Tff7b72+Tff7b72= T79c0ff1

T8b949e# done writing segments
Tff7b72selfTff7b72.Td2a8ffappend_checksumTb4b4b4(Te6edf3fTb4b4b4, Te6edf3checksumTb4b4b4)
Te6edf3image_length Tff7b72= Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffsecure_padTb4b4b4:
Tff7b72assert Tb4b4b4(Tb4b4b4(Te6edf3image_length Tff7b72+ Te6edf3space_after_checksumTb4b4b4) Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGNTb4b4b4) Tff7b72== T79c0ff0

T8b949e# kinda hacky: go back to the initial header and write the new segment count
T8b949e# that includes padding segments. This header is not checksummed
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Tffa657chrTb4b4b4(Te6edf3total_segmentsTb4b4b4)Tb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4: T8b949e# Python 3
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Tffa657bytesTb4b4b4(Tb4b4b4[Te6edf3total_segmentsTb4b4b4]Tb4b4b4)Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffappend_digestTb4b4b4:
T8b949e# calculate the SHA256 of the whole file and append it
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3digest Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffsha256Tb4b4b4(Tb4b4b4)
Te6edf3digestTff7b72.Td2a8ffupdateTb4b4b4(Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3image_lengthTb4b4b4)Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3digestTff7b72.Td2a8ffdigestTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72with Tffa657openTb4b4b4(Te6edf3filenameTb4b4b4, Ta5d6ff'Ta5d6ffwbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3real_fileTb4b4b4:
Te6edf3real_fileTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3fTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffsave_flash_segmentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e""" Save the next segment to the image file, return next checksum value if provided """
Te6edf3segment_end_pos Tff7b72= Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72+ Tffa657lenTb4b4b4(Te6edf3segmentTff7b72.Td2a8ffdataTb4b4b4) Tff7b72+ Tff7b72selfTff7b72.Td2a8ffSEG_HEADER_LEN
Te6edf3segment_len_remainder Tff7b72= Te6edf3segment_end_pos Tff7b72% Tff7b72selfTff7b72.Td2a8ffIROM_ALIGN
Tff7b72if Te6edf3segment_len_remainder Tff7b72< T79c0ff0x24Tb4b4b4:
T8b949e# Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the
T8b949e# last MMU page, if an IROM/DROM segment was < 0x24 bytes over the page boundary.
Te6edf3segmentTff7b72.Td2a8ffdata Tff7b72+Tff7b72= Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff' Tff7b72* Tb4b4b4(T79c0ff0x24 Tff7b72- Te6edf3segment_len_remainderTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffsave_segmentTb4b4b4(Te6edf3fTb4b4b4, Te6edf3segmentTb4b4b4, Te6edf3checksumTb4b4b4)

Tff7b72def Td2a8ffload_extended_headerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3load_fileTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffsplit_byteTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3n Tff7b72& T79c0ff0x0FTb4b4b4, Tb4b4b4(Te6edf3n Tff7b72>> T79c0ff4Tb4b4b4) Tff7b72& T79c0ff0x0FTb4b4b4)

Te6edf3fields Tff7b72= Tffa657listTb4b4b4(Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Tff7b72selfTff7b72.Td2a8ffEXTENDED_HEADER_STRUCT_FMTTb4b4b4, Te6edf3load_fileTff7b72.Td2a8ffreadTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4)Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffwp_pin Tff7b72= Te6edf3fieldsTb4b4b4[T79c0ff0Tb4b4b4]

T8b949e# SPI pin drive stengths are two per byte
Tff7b72selfTff7b72.Td2a8ffclk_drvTb4b4b4, Tff7b72selfTff7b72.Td2a8ffq_drv Tff7b72= Te6edf3split_byteTb4b4b4(Te6edf3fieldsTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffd_drvTb4b4b4, Tff7b72selfTff7b72.Td2a8ffcs_drv Tff7b72= Te6edf3split_byteTb4b4b4(Te6edf3fieldsTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffhd_drvTb4b4b4, Tff7b72selfTff7b72.Td2a8ffwp_drv Tff7b72= Te6edf3split_byteTb4b4b4(Te6edf3fieldsTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4)

Te6edf3chip_id Tff7b72= Te6edf3fieldsTb4b4b4[T79c0ff4Tb4b4b4]
Tff7b72if Te6edf3chip_id Tff7b72!= Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffIMAGE_CHIP_IDTb4b4b4:
Tffa657printTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffUnexpected chip id in image. Expected Tffd700%dTa5d6ff but value was Tffd700%dTa5d6ff. Ta5d6ff"
Ta5d6ff"Ta5d6ffIs this image for a different chip model?Ta5d6ff"Tb4b4b4) Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffIMAGE_CHIP_IDTb4b4b4, Te6edf3chip_idTb4b4b4)Tb4b4b4)

T8b949e# reserved fields in the middle should all be zero
Tff7b72if Tffa657anyTb4b4b4(Te6edf3f Tff7b72for Te6edf3f Tff7b72in Te6edf3fieldsTb4b4b4[T79c0ff6Tb4b4b4:Tff7b72-T79c0ff1Tb4b4b4] Tff7b72if Te6edf3f Tff7b72!= T79c0ff0Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWarning: some reserved header fields have non-zero values. This image may be from a newer esptool.py?Ta5d6ff"Tb4b4b4)

Te6edf3append_digest Tff7b72= Te6edf3fieldsTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4] T8b949e# last byte is append_digest
Tff7b72if Te6edf3append_digest Tff7b72in Tb4b4b4[T79c0ff0Tb4b4b4, T79c0ff1Tb4b4b4]Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffappend_digest Tff7b72= Tb4b4b4(Te6edf3append_digest Tff7b72== T79c0ff1Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid value for append_digest field (0xTffd700%02xTa5d6ff). Should be 0 or 1.Ta5d6ff"Tb4b4b4, Te6edf3append_digestTb4b4b4)

Tff7b72def Td2a8ffsave_extended_headerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3save_fileTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffjoin_byteTb4b4b4(Te6edf3lnTb4b4b4, Te6edf3hnTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(Te6edf3ln Tff7b72& T79c0ff0x0FTb4b4b4) Tff7b72+ Tb4b4b4(Tb4b4b4(Te6edf3hn Tff7b72& T79c0ff0x0FTb4b4b4) Tff7b72<< T79c0ff4Tb4b4b4)

Te6edf3append_digest Tff7b72= T79c0ff1 Tff7b72if Tff7b72selfTff7b72.Td2a8ffappend_digest Tff7b72else T79c0ff0

Te6edf3fields Tff7b72= Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffwp_pinTb4b4b4,
Te6edf3join_byteTb4b4b4(Tff7b72selfTff7b72.Td2a8ffclk_drvTb4b4b4, Tff7b72selfTff7b72.Td2a8ffq_drvTb4b4b4)Tb4b4b4,
Te6edf3join_byteTb4b4b4(Tff7b72selfTff7b72.Td2a8ffd_drvTb4b4b4, Tff7b72selfTff7b72.Td2a8ffcs_drvTb4b4b4)Tb4b4b4,
Te6edf3join_byteTb4b4b4(Tff7b72selfTff7b72.Td2a8ffhd_drvTb4b4b4, Tff7b72selfTff7b72.Td2a8ffwp_drvTb4b4b4)Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffIMAGE_CHIP_IDTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffmin_revTb4b4b4]
Te6edf3fields Tff7b72+Tff7b72= Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72* T79c0ff8 T8b949e# padding
Te6edf3fields Tff7b72+Tff7b72= Tb4b4b4[Te6edf3append_digestTb4b4b4]

Te6edf3packed Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Tff7b72selfTff7b72.Td2a8ffEXTENDED_HEADER_STRUCT_FMTTb4b4b4, Tff7b72*Te6edf3fieldsTb4b4b4)
Te6edf3save_fileTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3packedTb4b4b4)


Te6edf3ESP32ROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP32FirmwareImage


Tff7b72class T56d364ESP32S2FirmwareImageTb4b4b4(Te6edf3ESP32FirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" ESP32S2 Firmware Image almost exactly the same as ESP32FirmwareImage """
Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP32S2ROM


Te6edf3ESP32S2ROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP32S2FirmwareImage


Tff7b72class T56d364ESP32S3BETA2FirmwareImageTb4b4b4(Te6edf3ESP32FirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage """
Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP32S3BETA2ROM


Te6edf3ESP32S3BETA2ROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP32S3BETA2FirmwareImage


Tff7b72class T56d364ESP32S3BETA3FirmwareImageTb4b4b4(Te6edf3ESP32FirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage """
Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP32S3BETA3ROM


Te6edf3ESP32S3BETA3ROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP32S3BETA3FirmwareImage


Tff7b72class T56d364ESP32C3FirmwareImageTb4b4b4(Te6edf3ESP32FirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" ESP32C3 Firmware Image almost exactly the same as ESP32FirmwareImage """
Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP32C3ROM


Te6edf3ESP32C3ROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP32C3FirmwareImage


Tff7b72class T56d364ESP32C6BETAFirmwareImageTb4b4b4(Te6edf3ESP32FirmwareImageTb4b4b4)Tb4b4b4:
T8b949e""" ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage """
Te6edf3ROM_LOADER Tff7b72= Te6edf3ESP32C6BETAROM


Te6edf3ESP32C6BETAROMTff7b72.Td2a8ffBOOTLOADER_IMAGE Tff7b72= Te6edf3ESP32C6BETAFirmwareImage


Tff7b72class T56d364ELFFileTb4b4b4(Tffa657objectTb4b4b4)Tb4b4b4:
Te6edf3SEC_TYPE_PROGBITS Tff7b72= T79c0ff0x01
Te6edf3SEC_TYPE_STRTAB Tff7b72= T79c0ff0x03

Te6edf3LEN_SEC_HEADER Tff7b72= T79c0ff0x28

Te6edf3SEG_TYPE_LOAD Tff7b72= T79c0ff0x01
Te6edf3LEN_SEG_HEADER Tff7b72= T79c0ff0x20

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e# Load sections from the ELF file
Tff7b72selfTff7b72.Td2a8ffname Tff7b72= Te6edf3name
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4, Ta5d6ff'Ta5d6ffrbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_read_elf_fileTb4b4b4(Te6edf3fTb4b4b4)

Tff7b72def Td2a8ffget_sectionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3section_nameTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3s Tff7b72in Tff7b72selfTff7b72.Td2a8ffsectionsTb4b4b4:
Tff7b72if Te6edf3sTff7b72.Td2a8ffname Tff7b72== Te6edf3section_nameTb4b4b4:
Tff7b72return Te6edf3s
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo section Tffd700%sTa5d6ff in ELF fileTa5d6ff" Tff7b72% Te6edf3section_nameTb4b4b4)

Tff7b72def Td2a8ff_read_elf_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4)Tb4b4b4:
T8b949e# read the ELF file header
Te6edf3LEN_FILE_HEADER Tff7b72= T79c0ff0x34
Tff7b72tryTb4b4b4:
Tb4b4b4(Te6edf3identTb4b4b4, Te6edf3_typeTb4b4b4, Te6edf3machineTb4b4b4, Te6edf3_versionTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffentrypointTb4b4b4, Te6edf3_phoffTb4b4b4, Te6edf3shoffTb4b4b4, Te6edf3_flagsTb4b4b4,
Te6edf3_ehsizeTb4b4b4, Te6edf3_phentsizeTb4b4b4, Te6edf3_phnumTb4b4b4, Te6edf3shentsizeTb4b4b4,
Te6edf3shnumTb4b4b4, Te6edf3shstrndxTb4b4b4) Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff<16sHHLLLLLHHHHHHTa5d6ff"Tb4b4b4, Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3LEN_FILE_HEADERTb4b4b4)Tb4b4b4)
Tff7b72except Te6edf3structTff7b72.Td2a8fferror Tff7b72as Te6edf3eTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffFailed to read a valid ELF header from Tffd700%sTa5d6ff: Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4)

Tff7b72if Te6edf3byteTb4b4b4(Te6edf3identTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72!= T79c0ff0x7f Tff7b72or Te6edf3identTb4b4b4[T79c0ff1Tb4b4b4:T79c0ff4Tb4b4b4] Tff7b72!= Ta5d6ffbTa5d6ff'Ta5d6ffELFTa5d6ff'Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff has invalid ELF magic headerTa5d6ff" Tff7b72% Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4)
Tff7b72if Te6edf3machine Tff7b72not Tff7b72in Tb4b4b4[T79c0ff0x5eTb4b4b4, T79c0ff0xf3Tb4b4b4]Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff does not appear to be an Xtensa or an RISCV ELF file. e_machine=Tffd700%04xTa5d6ff" Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4, Te6edf3machineTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3shentsize Tff7b72!= Tff7b72selfTff7b72.Td2a8ffLEN_SEC_HEADERTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff has unexpected section header entry size 0xTffd700%xTa5d6ff (not 0xTffd700%xTa5d6ff)Ta5d6ff" Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4, Te6edf3shentsizeTb4b4b4, Tff7b72selfTff7b72.Td2a8ffLEN_SEC_HEADERTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3shnum Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Tffd700%sTa5d6ff has 0 section headersTa5d6ff" Tff7b72% Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_read_sectionsTb4b4b4(Te6edf3fTb4b4b4, Te6edf3shoffTb4b4b4, Te6edf3shnumTb4b4b4, Te6edf3shstrndxTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_read_segmentsTb4b4b4(Te6edf3fTb4b4b4, Te6edf3_phoffTb4b4b4, Te6edf3_phnumTb4b4b4, Te6edf3shstrndxTb4b4b4)

Tff7b72def Td2a8ff_read_sectionsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3section_header_offsTb4b4b4, Te6edf3section_header_countTb4b4b4, Te6edf3shstrndxTb4b4b4)Tb4b4b4:
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3section_header_offsTb4b4b4)
Te6edf3len_bytes Tff7b72= Te6edf3section_header_count Tff7b72* Tff7b72selfTff7b72.Td2a8ffLEN_SEC_HEADER
Te6edf3section_header Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3len_bytesTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3section_headerTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo section header found at offset Tffd700%04xTa5d6ff in ELF file.Ta5d6ff" Tff7b72% Te6edf3section_header_offsTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3section_headerTb4b4b4) Tff7b72!= Tb4b4b4(Te6edf3len_bytesTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffOnly read 0xTffd700%xTa5d6ff bytes from section header (expected 0xTffd700%xTa5d6ff.) Truncated ELF file?Ta5d6ff" Tff7b72% Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3section_headerTb4b4b4)Tb4b4b4, Te6edf3len_bytesTb4b4b4)Tb4b4b4)

T8b949e# walk through the section header and extract all sections
Te6edf3section_header_offsets Tff7b72= Tffa657rangeTb4b4b4(T79c0ff0Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3section_headerTb4b4b4)Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffLEN_SEC_HEADERTb4b4b4)

Tff7b72def Td2a8ffread_section_headerTb4b4b4(Te6edf3offsTb4b4b4)Tb4b4b4:
Te6edf3name_offsTb4b4b4, Te6edf3sec_typeTb4b4b4, Te6edf3_flagsTb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3sec_offsTb4b4b4, Te6edf3size Tff7b72= Te6edf3structTff7b72.Td2a8ffunpack_fromTb4b4b4(Ta5d6ff"Ta5d6ff<LLLLLLTa5d6ff"Tb4b4b4, Te6edf3section_headerTb4b4b4[Te6edf3offsTb4b4b4:Tb4b4b4]Tb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3name_offsTb4b4b4, Te6edf3sec_typeTb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3sec_offsTb4b4b4)
Te6edf3all_sections Tff7b72= Tb4b4b4[Te6edf3read_section_headerTb4b4b4(Te6edf3offsTb4b4b4) Tff7b72for Te6edf3offs Tff7b72in Te6edf3section_header_offsetsTb4b4b4]
Te6edf3prog_sections Tff7b72= Tb4b4b4[Te6edf3s Tff7b72for Te6edf3s Tff7b72in Te6edf3all_sections Tff7b72if Te6edf3sTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72== Te6edf3ELFFileTff7b72.Td2a8ffSEC_TYPE_PROGBITSTb4b4b4]

T8b949e# search for the string table section
Tff7b72if Tff7b72not Tb4b4b4(Te6edf3shstrndx Tff7b72* Tff7b72selfTff7b72.Td2a8ffLEN_SEC_HEADERTb4b4b4) Tff7b72in Te6edf3section_header_offsetsTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffELF file has no STRTAB section at shstrndx Tffd700%dTa5d6ff" Tff7b72% Te6edf3shstrndxTb4b4b4)
Te6edf3_Tb4b4b4, Te6edf3sec_typeTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3sec_sizeTb4b4b4, Te6edf3sec_offs Tff7b72= Te6edf3read_section_headerTb4b4b4(Te6edf3shstrndx Tff7b72* Tff7b72selfTff7b72.Td2a8ffLEN_SEC_HEADERTb4b4b4)
Tff7b72if Te6edf3sec_type Tff7b72!= Te6edf3ELFFileTff7b72.Td2a8ffSEC_TYPE_STRTABTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: ELF file has incorrect STRTAB section type 0xTffd700%02xTa5d6ff' Tff7b72% Te6edf3sec_typeTb4b4b4)
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3sec_offsTb4b4b4)
Te6edf3string_table Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3sec_sizeTb4b4b4)

T8b949e# build the real list of ELFSections by reading the actual section names from the
T8b949e# string table section, and actual data for each section from the ELF file itself
Tff7b72def Td2a8fflookup_stringTb4b4b4(Te6edf3offsTb4b4b4)Tb4b4b4:
Te6edf3raw Tff7b72= Te6edf3string_tableTb4b4b4[Te6edf3offsTb4b4b4:Tb4b4b4]
Tff7b72return Te6edf3rawTb4b4b4[Tb4b4b4:Te6edf3rawTff7b72.Td2a8ffindexTb4b4b4(Ta5d6ffbTa5d6ff'Tffea00\x00Ta5d6ff'Tb4b4b4)Tb4b4b4]

Tff7b72def Td2a8ffread_dataTb4b4b4(Te6edf3offsTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3offsTb4b4b4)
Tff7b72return Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3sizeTb4b4b4)

Te6edf3prog_sections Tff7b72= Tb4b4b4[Te6edf3ELFSectionTb4b4b4(Te6edf3lookup_stringTb4b4b4(Te6edf3n_offsTb4b4b4)Tb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3read_dataTb4b4b4(Te6edf3offsTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4) Tff7b72for Tb4b4b4(Te6edf3n_offsTb4b4b4, Te6edf3_typeTb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3offsTb4b4b4) Tff7b72in Te6edf3prog_sections
Tff7b72if Te6edf3lma Tff7b72!= T79c0ff0 Tff7b72and Te6edf3size Tff7b72> T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffsections Tff7b72= Te6edf3prog_sections

Tff7b72def Td2a8ff_read_segmentsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fTb4b4b4, Te6edf3segment_header_offsTb4b4b4, Te6edf3segment_header_countTb4b4b4, Te6edf3shstrndxTb4b4b4)Tb4b4b4:
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3segment_header_offsTb4b4b4)
Te6edf3len_bytes Tff7b72= Te6edf3segment_header_count Tff7b72* Tff7b72selfTff7b72.Td2a8ffLEN_SEG_HEADER
Te6edf3segment_header Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3len_bytesTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3segment_headerTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo segment header found at offset Tffd700%04xTa5d6ff in ELF file.Ta5d6ff" Tff7b72% Te6edf3segment_header_offsTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3segment_headerTb4b4b4) Tff7b72!= Tb4b4b4(Te6edf3len_bytesTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffOnly read 0xTffd700%xTa5d6ff bytes from segment header (expected 0xTffd700%xTa5d6ff.) Truncated ELF file?Ta5d6ff" Tff7b72% Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3segment_headerTb4b4b4)Tb4b4b4, Te6edf3len_bytesTb4b4b4)Tb4b4b4)

T8b949e# walk through the segment header and extract all segments
Te6edf3segment_header_offsets Tff7b72= Tffa657rangeTb4b4b4(T79c0ff0Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3segment_headerTb4b4b4)Tb4b4b4, Tff7b72selfTff7b72.Td2a8ffLEN_SEG_HEADERTb4b4b4)

Tff7b72def Td2a8ffread_segment_headerTb4b4b4(Te6edf3offsTb4b4b4)Tb4b4b4:
Te6edf3seg_typeTb4b4b4, Te6edf3seg_offsTb4b4b4, Te6edf3_vaddrTb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3_memsizeTb4b4b4, Te6edf3_flagsTb4b4b4, Te6edf3_align Tff7b72= Te6edf3structTff7b72.Td2a8ffunpack_fromTb4b4b4(Ta5d6ff"Ta5d6ff<LLLLLLLLTa5d6ff"Tb4b4b4, Te6edf3segment_headerTb4b4b4[Te6edf3offsTb4b4b4:Tb4b4b4]Tb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3seg_typeTb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3seg_offsTb4b4b4)
Te6edf3all_segments Tff7b72= Tb4b4b4[Te6edf3read_segment_headerTb4b4b4(Te6edf3offsTb4b4b4) Tff7b72for Te6edf3offs Tff7b72in Te6edf3segment_header_offsetsTb4b4b4]
Te6edf3prog_segments Tff7b72= Tb4b4b4[Te6edf3s Tff7b72for Te6edf3s Tff7b72in Te6edf3all_segments Tff7b72if Te6edf3sTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Te6edf3ELFFileTff7b72.Td2a8ffSEG_TYPE_LOADTb4b4b4]

Tff7b72def Td2a8ffread_dataTb4b4b4(Te6edf3offsTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3offsTb4b4b4)
Tff7b72return Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Te6edf3sizeTb4b4b4)

Te6edf3prog_segments Tff7b72= Tb4b4b4[Te6edf3ELFSectionTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ffPHDRTa5d6ff'Tb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3read_dataTb4b4b4(Te6edf3offsTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4) Tff7b72for Tb4b4b4(Te6edf3_typeTb4b4b4, Te6edf3lmaTb4b4b4, Te6edf3sizeTb4b4b4, Te6edf3offsTb4b4b4) Tff7b72in Te6edf3prog_segments
Tff7b72if Te6edf3lma Tff7b72!= T79c0ff0 Tff7b72and Te6edf3size Tff7b72> T79c0ff0Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffsegments Tff7b72= Te6edf3prog_segments

Tff7b72def Td2a8ffsha256Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# return SHA256 hash of the input ELF file
Te6edf3sha256 Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffsha256Tb4b4b4(Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4, Ta5d6ff'Ta5d6ffrbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3sha256Tff7b72.Td2a8ffupdateTb4b4b4(Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3sha256Tff7b72.Td2a8ffdigestTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8ffslip_readerTb4b4b4(Te6edf3portTb4b4b4, Te6edf3trace_functionTb4b4b4)Tb4b4b4:
T8b949e"""Generator to read SLIP packets from a serial port.
Yields one full SLIP packet at a time, raises exception on timeout or invalid data.

Designed to avoid too many calls to serial.read(1), which can bog
down on slow systems.
"""
Te6edf3partial_packet Tff7b72= Tff7b72None
Te6edf3in_escape Tff7b72= Tff7b72False
Tff7b72while Tff7b72TrueTb4b4b4:
Te6edf3waiting Tff7b72= Te6edf3portTff7b72.Td2a8ffinWaitingTb4b4b4(Tb4b4b4)
Te6edf3read_bytes Tff7b72= Te6edf3portTff7b72.Td2a8ffreadTb4b4b4(T79c0ff1 Tff7b72if Te6edf3waiting Tff7b72== T79c0ff0 Tff7b72else Te6edf3waitingTb4b4b4)
Tff7b72if Te6edf3read_bytes Tff7b72== Ta5d6ffbTa5d6ff'Ta5d6ff'Tb4b4b4:
Te6edf3waiting_for Tff7b72= Ta5d6ff"Ta5d6ffheaderTa5d6ff" Tff7b72if Te6edf3partial_packet Tff7b72is Tff7b72None Tff7b72else Ta5d6ff"Ta5d6ffcontentTa5d6ff"
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffTimed out waiting for packet Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3waiting_forTb4b4b4)
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffTimed out waiting for packet Tffd700%sTa5d6ff" Tff7b72% Te6edf3waiting_forTb4b4b4)
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffRead Tffd700%dTa5d6ff bytes: Tffd700%sTa5d6ff"Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3read_bytesTb4b4b4)Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3read_bytesTb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3b Tff7b72in Te6edf3read_bytesTb4b4b4:
Tff7b72if Tffa657typeTb4b4b4(Te6edf3bTb4b4b4) Tff7b72is Tffa657intTb4b4b4:
Te6edf3b Tff7b72= Tffa657bytesTb4b4b4(Tb4b4b4[Te6edf3bTb4b4b4]Tb4b4b4) T8b949e# python 2/3 compat

Tff7b72if Te6edf3partial_packet Tff7b72is Tff7b72NoneTb4b4b4: T8b949e# waiting for packet header
Tff7b72if Te6edf3b Tff7b72== Ta5d6ffbTa5d6ff'Tffea00\xc0Ta5d6ff'Tb4b4b4:
Te6edf3partial_packet Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffRead invalid data: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3read_bytesTb4b4b4)Tb4b4b4)
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffRemaining data in serial buffer: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3portTff7b72.Td2a8ffreadTb4b4b4(Te6edf3portTff7b72.Td2a8ffinWaitingTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffInvalid head of packet (0xTffd700%sTa5d6ff)Ta5d6ff' Tff7b72% Te6edf3hexifyTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4)
Tff7b72elif Te6edf3in_escapeTb4b4b4: T8b949e# part-way through escape sequence
Te6edf3in_escape Tff7b72= Tff7b72False
Tff7b72if Te6edf3b Tff7b72== Ta5d6ffbTa5d6ff'Tffea00\xdcTa5d6ff'Tb4b4b4:
Te6edf3partial_packet Tff7b72+Tff7b72= Ta5d6ffbTa5d6ff'Tffea00\xc0Ta5d6ff'
Tff7b72elif Te6edf3b Tff7b72== Ta5d6ffbTa5d6ff'Tffea00\xddTa5d6ff'Tb4b4b4:
Te6edf3partial_packet Tff7b72+Tff7b72= Ta5d6ffbTa5d6ff'Tffea00\xdbTa5d6ff'
Tff7b72elseTb4b4b4:
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffRead invalid data: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3read_bytesTb4b4b4)Tb4b4b4)
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffRemaining data in serial buffer: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3portTff7b72.Td2a8ffreadTb4b4b4(Te6edf3portTff7b72.Td2a8ffinWaitingTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffInvalid SLIP escape (0xdb, 0xTffd700%sTa5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3hexifyTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72elif Te6edf3b Tff7b72== Ta5d6ffbTa5d6ff'Tffea00\xdbTa5d6ff'Tb4b4b4: T8b949e# start of escape sequence
Te6edf3in_escape Tff7b72= Tff7b72True
Tff7b72elif Te6edf3b Tff7b72== Ta5d6ffbTa5d6ff'Tffea00\xc0Ta5d6ff'Tb4b4b4: T8b949e# end of packet
Te6edf3trace_functionTb4b4b4(Ta5d6ff"Ta5d6ffReceived full packet: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3HexFormatterTb4b4b4(Te6edf3partial_packetTb4b4b4)Tb4b4b4)
Tff7b72yield Te6edf3partial_packet
Te6edf3partial_packet Tff7b72= Tff7b72None
Tff7b72elseTb4b4b4: T8b949e# normal byte in packet
Te6edf3partial_packet Tff7b72+Tff7b72= Te6edf3b


Tff7b72def Td2a8ffarg_auto_intTb4b4b4(Te6edf3xTb4b4b4)Tb4b4b4:
Tff7b72return Tffa657intTb4b4b4(Te6edf3xTb4b4b4, T79c0ff0Tb4b4b4)


Tff7b72def Td2a8ffdiv_roundupTb4b4b4(Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4:
T8b949e""" Return a/b rounded up to nearest integer,
equivalent result to int(math.ceil(float(int(a)) / float(int(b))), only
without possible floating point accuracy errors.
"""
Tff7b72return Tb4b4b4(Tffa657intTb4b4b4(Te6edf3aTb4b4b4) Tff7b72+ Tffa657intTb4b4b4(Te6edf3bTb4b4b4) Tff7b72- T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Tffa657intTb4b4b4(Te6edf3bTb4b4b4)


Tff7b72def Td2a8ffalign_file_positionTb4b4b4(Te6edf3fTb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4:
T8b949e""" Align the position in the file to the next block of specified size """
Te6edf3align Tff7b72= Tb4b4b4(Te6edf3size Tff7b72- T79c0ff1Tb4b4b4) Tff7b72- Tb4b4b4(Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72% Te6edf3sizeTb4b4b4)
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3alignTb4b4b4, T79c0ff1Tb4b4b4)


Tff7b72def Td2a8ffflash_size_bytesTb4b4b4(Te6edf3sizeTb4b4b4)Tb4b4b4:
T8b949e""" Given a flash size of the type passed in args.flash_size
(ie 512KB or 1MB) then return the size in bytes.
"""
Tff7b72if Ta5d6ff"Ta5d6ffMBTa5d6ff" Tff7b72in Te6edf3sizeTb4b4b4:
Tff7b72return Tffa657intTb4b4b4(Te6edf3sizeTb4b4b4[Tb4b4b4:Te6edf3sizeTff7b72.Td2a8ffindexTb4b4b4(Ta5d6ff"Ta5d6ffMBTa5d6ff"Tb4b4b4)Tb4b4b4]Tb4b4b4) Tff7b72* T79c0ff1024 Tff7b72* T79c0ff1024
Tff7b72elif Ta5d6ff"Ta5d6ffKBTa5d6ff" Tff7b72in Te6edf3sizeTb4b4b4:
Tff7b72return Tffa657intTb4b4b4(Te6edf3sizeTb4b4b4[Tb4b4b4:Te6edf3sizeTff7b72.Td2a8ffindexTb4b4b4(Ta5d6ff"Ta5d6ffKBTa5d6ff"Tb4b4b4)Tb4b4b4]Tb4b4b4) Tff7b72* T79c0ff1024
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnknown size Tffd700%sTa5d6ff" Tff7b72% Te6edf3sizeTb4b4b4)


Tff7b72def Td2a8ffhexifyTb4b4b4(Te6edf3sTb4b4b4, Te6edf3uppercaseTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4:
Te6edf3format_str Tff7b72= Ta5d6ff'Tffd700%02XTa5d6ff' Tff7b72if Te6edf3uppercase Tff7b72else Ta5d6ff'Tffd700%02xTa5d6ff'
Tff7b72if Tff7b72not Te6edf3PYTHON2Tb4b4b4:
Tff7b72return Ta5d6ff'Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3format_str Tff7b72% Te6edf3c Tff7b72for Te6edf3c Tff7b72in Te6edf3sTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72return Ta5d6ff'Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3format_str Tff7b72% Tffa657ordTb4b4b4(Te6edf3cTb4b4b4) Tff7b72for Te6edf3c Tff7b72in Te6edf3sTb4b4b4)


Tff7b72class T56d364HexFormatterTb4b4b4(Tffa657objectTb4b4b4)Tb4b4b4:
T8b949e"""
Wrapper class which takes binary data in its constructor
and returns a hex string as it's __str__ method.

This is intended for "lazy formatting" of trace() output
in hex format. Avoids overhead (significant on slow computers)
of generating long hex strings even if tracing is disabled.

Note that this doesn't save any overhead if passed as an
argument to "%", only when passed to trace()

If auto_split is set (default), any long line (> 16 bytes) will be
printed as separately indented lines, with ASCII decoding at the end
of each line.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3binary_stringTb4b4b4, Te6edf3auto_splitTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_s Tff7b72= Te6edf3binary_string
Tff7b72selfTff7b72.Td2a8ff_auto_split Tff7b72= Te6edf3auto_split

Tff7b72def Tff7b72__str__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_auto_split Tff7b72and Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_sTb4b4b4) Tff7b72> T79c0ff16Tb4b4b4:
Te6edf3result Tff7b72= Ta5d6ff"Ta5d6ff"
Te6edf3s Tff7b72= Tff7b72selfTff7b72.Td2a8ff_s
Tff7b72while Tffa657lenTb4b4b4(Te6edf3sTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3line Tff7b72= Te6edf3sTb4b4b4[Tb4b4b4:T79c0ff16Tb4b4b4]
Te6edf3ascii_line Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3c Tff7b72if Tb4b4b4(Te6edf3c Tff7b72== Ta5d6ff'Ta5d6ff Ta5d6ff' Tff7b72or Tb4b4b4(Te6edf3c Tff7b72in Te6edf3stringTff7b72.Td2a8ffprintable Tff7b72and Te6edf3c Tff7b72not Tff7b72in Te6edf3stringTff7b72.Td2a8ffwhitespaceTb4b4b4)Tb4b4b4)
Tff7b72else Ta5d6ff'Ta5d6ff.Ta5d6ff' Tff7b72for Te6edf3c Tff7b72in Te6edf3lineTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff'Ta5d6ffasciiTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffreplaceTa5d6ff'Tb4b4b4)Tb4b4b4)
Te6edf3s Tff7b72= Te6edf3sTb4b4b4[T79c0ff16Tb4b4b4:Tb4b4b4]
Te6edf3result Tff7b72+Tff7b72= Ta5d6ff"Tffea00\nTa5d6ff Tffd700%-16sTa5d6ff Tffd700%-16sTa5d6ff | Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3hexifyTb4b4b4(Te6edf3lineTb4b4b4[Tb4b4b4:T79c0ff8Tb4b4b4]Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4, Te6edf3hexifyTb4b4b4(Te6edf3lineTb4b4b4[T79c0ff8Tb4b4b4:Tb4b4b4]Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4, Te6edf3ascii_lineTb4b4b4)
Tff7b72return Te6edf3result
Tff7b72elseTb4b4b4:
Tff7b72return Te6edf3hexifyTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_sTb4b4b4, Tff7b72FalseTb4b4b4)


Tff7b72def Td2a8ffpad_toTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3alignmentTb4b4b4, Te6edf3pad_characterTff7b72=Ta5d6ffbTa5d6ff'Tffea00\xFFTa5d6ff'Tb4b4b4)Tb4b4b4:
T8b949e""" Pad to the next alignment boundary """
Te6edf3pad_mod Tff7b72= Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72% Te6edf3alignment
Tff7b72if Te6edf3pad_mod Tff7b72!= T79c0ff0Tb4b4b4:
Te6edf3data Tff7b72+Tff7b72= Te6edf3pad_character Tff7b72* Tb4b4b4(Te6edf3alignment Tff7b72- Te6edf3pad_modTb4b4b4)
Tff7b72return Te6edf3data


Tff7b72class T56d364FatalErrorTb4b4b4(Tf85149RuntimeErrorTb4b4b4)Tb4b4b4:
T8b949e"""
Wrapper class for runtime errors that aren't caused by internal bugs, but by
ESP8266 responses or input content.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3messageTb4b4b4)Tb4b4b4:
Tf85149RuntimeErrorTff7b72.Td2a8ff__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3messageTb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ffWithResultTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3resultTb4b4b4)Tb4b4b4:
T8b949e"""
Return a fatal error object that appends the hex values of
'result' as a string formatted argument.
"""
Te6edf3message Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff (result was Tffd700%sTa5d6ff)Ta5d6ff" Tff7b72% Te6edf3hexifyTb4b4b4(Te6edf3resultTb4b4b4)
Tff7b72return Te6edf3FatalErrorTb4b4b4(Te6edf3messageTb4b4b4)


Tff7b72class T56d364NotImplementedInROMErrorTb4b4b4(Te6edf3FatalErrorTb4b4b4)Tb4b4b4:
T8b949e"""
Wrapper class for the error thrown when a particular ESP bootloader function
is not implemented in the ROM bootloader.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bootloaderTb4b4b4, Te6edf3funcTb4b4b4)Tb4b4b4:
Te6edf3FatalErrorTff7b72.Td2a8ff__init__Tb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Tffd700%sTa5d6ff ROM does not support function Tffd700%sTa5d6ff.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3bootloaderTff7b72.Td2a8ffCHIP_NAMETb4b4b4, Te6edf3funcTff7b72.Td2a8ff__name__Tb4b4b4)Tb4b4b4)


Tff7b72class T56d364NotSupportedErrorTb4b4b4(Te6edf3FatalErrorTb4b4b4)Tb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3espTb4b4b4, Te6edf3function_nameTb4b4b4)Tb4b4b4:
Te6edf3FatalErrorTff7b72.Td2a8ff__init__Tb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffFunction Tffd700%sTa5d6ff is not supported for Tffd700%sTa5d6ff.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3function_nameTb4b4b4, Te6edf3espTff7b72.Td2a8ffCHIP_NAMETb4b4b4)Tb4b4b4)

T8b949e# "Operation" commands, executable at command line. One function each
T8b949e#
T8b949e# Each function takes either two args (<ESPLoader instance>, <args>) or a single <args>
T8b949e# argument.


Tff7b72class T56d364UnsupportedCommandErrorTb4b4b4(Tf85149RuntimeErrorTb4b4b4)Tb4b4b4:
T8b949e"""
Wrapper class for when ROM loader returns an invalid command response.

Usually this indicates the loader is running in Secure Download Mode.
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3espTb4b4b4, Te6edf3opTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3espTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffThis command (0xTffd700%xTa5d6ff) is not supported in Secure Download ModeTa5d6ff" Tff7b72% Te6edf3op
Tff7b72elseTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffInvalid (unsupported) command 0xTffd700%xTa5d6ff" Tff7b72% Te6edf3op
Tf85149RuntimeErrorTff7b72.Td2a8ff__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3msgTb4b4b4)


Tff7b72def Td2a8ffload_ramTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3LoadFirmwareImageTb4b4b4(Te6edf3espTff7b72.Td2a8ffCHIP_NAMETb4b4b4, Te6edf3argsTff7b72.Td2a8fffilenameTb4b4b4)

Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffRAM boot...Ta5d6ff'Tb4b4b4)
Tff7b72for Te6edf3seg Tff7b72in Te6edf3imageTff7b72.Td2a8ffsegmentsTb4b4b4:
Te6edf3size Tff7b72= Tffa657lenTb4b4b4(Te6edf3segTff7b72.Td2a8ffdataTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffDownloading Tffd700%dTa5d6ff bytes at Tffd700%08xTa5d6ff...Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3segTff7b72.Td2a8ffaddrTb4b4b4)Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff'Ta5d6ff Ta5d6ff'Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3espTff7b72.Td2a8ffmem_beginTb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3div_roundupTb4b4b4(Te6edf3sizeTb4b4b4, Te6edf3espTff7b72.Td2a8ffESP_RAM_BLOCKTb4b4b4)Tb4b4b4, Te6edf3espTff7b72.Td2a8ffESP_RAM_BLOCKTb4b4b4, Te6edf3segTff7b72.Td2a8ffaddrTb4b4b4)

Te6edf3seq Tff7b72= T79c0ff0
Tff7b72while Tffa657lenTb4b4b4(Te6edf3segTff7b72.Td2a8ffdataTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3espTff7b72.Td2a8ffmem_blockTb4b4b4(Te6edf3segTff7b72.Td2a8ffdataTb4b4b4[T79c0ff0Tb4b4b4:Te6edf3espTff7b72.Td2a8ffESP_RAM_BLOCKTb4b4b4]Tb4b4b4, Te6edf3seqTb4b4b4)
Te6edf3segTff7b72.Td2a8ffdata Tff7b72= Te6edf3segTff7b72.Td2a8ffdataTb4b4b4[Te6edf3espTff7b72.Td2a8ffESP_RAM_BLOCKTb4b4b4:Tb4b4b4]
Te6edf3seq Tff7b72+Tff7b72= T79c0ff1
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffdone!Ta5d6ff'Tb4b4b4)

Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffAll segments done, executing at Tffd700%08xTa5d6ff' Tff7b72% Te6edf3imageTff7b72.Td2a8ffentrypointTb4b4b4)
Te6edf3espTff7b72.Td2a8ffmem_finishTb4b4b4(Te6edf3imageTff7b72.Td2a8ffentrypointTb4b4b4)


Tff7b72def Td2a8ffread_memTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff0xTffd700%08xTa5d6ff = 0xTffd700%08xTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4, Te6edf3espTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4)Tb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffwrite_memTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3espTff7b72.Td2a8ffwrite_regTb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4, Te6edf3argsTff7b72.Td2a8ffvalueTb4b4b4, Te6edf3argsTff7b72.Td2a8ffmaskTb4b4b4, T79c0ff0Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWrote Tffd700%08xTa5d6ff, mask Tffd700%08xTa5d6ff to Tffd700%08xTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3argsTff7b72.Td2a8ffvalueTb4b4b4, Te6edf3argsTff7b72.Td2a8ffmaskTb4b4b4, Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffdump_memTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3argsTff7b72.Td2a8fffilenameTb4b4b4, Ta5d6ff'Ta5d6ffwbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3argsTff7b72.Td2a8ffsize Tff7b72/Tff7b72/ T79c0ff4Tb4b4b4)Tb4b4b4:
Te6edf3d Tff7b72= Te6edf3espTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddress Tff7b72+ Tb4b4b4(Te6edf3i Tff7b72* T79c0ff4Tb4b4b4)Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ff<ITa5d6ff'Tb4b4b4, Te6edf3dTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72% T79c0ff1024 Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3print_overwriteTb4b4b4(Ta5d6ff'Tffd700%dTa5d6ff bytes read... (Tffd700%dTa5d6ff Tffd700%%Ta5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff100 Tff7b72/Tff7b72/ Te6edf3argsTff7b72.Td2a8ffsizeTb4b4b4)Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3print_overwriteTb4b4b4(Ta5d6ff"Ta5d6ffRead Tffd700%dTa5d6ff bytesTa5d6ff" Tff7b72% Te6edf3fTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3last_lineTff7b72=Tff7b72TrueTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffDone!Ta5d6ff'Tb4b4b4)


Tff7b72def Td2a8ffdetect_flash_sizeTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72== Ta5d6ff'Ta5d6ffdetectTa5d6ff'Tb4b4b4:
Tff7b72if Te6edf3espTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffDetecting flash size is not supported in secure download mode. Need to manually specify flash size.Ta5d6ff"Tb4b4b4)
Te6edf3flash_id Tff7b72= Te6edf3espTff7b72.Td2a8ffflash_idTb4b4b4(Tb4b4b4)
Te6edf3size_id Tff7b72= Te6edf3flash_id Tff7b72>> T79c0ff16
Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72= Te6edf3DETECTED_FLASH_SIZESTff7b72.Td2a8ffgetTb4b4b4(Te6edf3size_idTb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72is Tff7b72NoneTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWarning: Could not auto-detect Flash size (FlashID=0xTffd700%xTa5d6ff, SizeID=0xTffd700%xTa5d6ff), defaulting to 4MBTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3flash_idTb4b4b4, Te6edf3size_idTb4b4b4)Tb4b4b4)
Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72= Ta5d6ff'Ta5d6ff4MBTa5d6ff'
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffAuto-detected Flash size:Ta5d6ff'Tb4b4b4, Te6edf3argsTff7b72.Td2a8ffflash_sizeTb4b4b4)


Tff7b72def Td2a8ff_update_image_flash_paramsTb4b4b4(Te6edf3espTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3argsTb4b4b4, Te6edf3imageTb4b4b4)Tb4b4b4:
T8b949e""" Modify the flash mode & size bytes if this looks like an executable bootloader image """
Tff7b72if Tffa657lenTb4b4b4(Te6edf3imageTb4b4b4) Tff7b72< T79c0ff8Tb4b4b4:
Tff7b72return Te6edf3image T8b949e# not long enough to be a bootloader image

T8b949e# unpack the (potential) image header
Te6edf3magicTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3flash_modeTb4b4b4, Te6edf3flash_size_freq Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ffBBBBTa5d6ff"Tb4b4b4, Te6edf3imageTb4b4b4[Tb4b4b4:T79c0ff4Tb4b4b4]Tb4b4b4)
Tff7b72if Te6edf3address Tff7b72!= Te6edf3espTff7b72.Td2a8ffBOOTLOADER_FLASH_OFFSETTb4b4b4:
Tff7b72return Te6edf3image T8b949e# not flashing bootloader offset, so don't modify this

Tff7b72if Tb4b4b4(Te6edf3argsTff7b72.Td2a8ffflash_modeTb4b4b4, Te6edf3argsTff7b72.Td2a8ffflash_freqTb4b4b4, Te6edf3argsTff7b72.Td2a8ffflash_sizeTb4b4b4) Tff7b72== Tb4b4b4(Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4,Tb4b4b4) Tff7b72* T79c0ff3Tb4b4b4:
Tff7b72return Te6edf3image T8b949e# all settings are 'keep', not modifying anything

T8b949e# easy check if this is an image: does it start with a magic byte?
Tff7b72if Te6edf3magic Tff7b72!= Te6edf3espTff7b72.Td2a8ffESP_IMAGE_MAGICTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWarning: Image file at 0xTffd700%xTa5d6ff doesnTa5d6ff'Ta5d6fft look like an image file, so not changing any flash settings.Ta5d6ff" Tff7b72% Te6edf3addressTb4b4b4)
Tff7b72return Te6edf3image

T8b949e# make sure this really is an image, and not just data that
T8b949e# starts with esp.ESP_IMAGE_MAGIC (mostly a problem for encrypted
T8b949e# images that happen to start with a magic byte
Tff7b72tryTb4b4b4:
Te6edf3test_image Tff7b72= Te6edf3espTff7b72.Td2a8ffBOOTLOADER_IMAGETb4b4b4(Te6edf3ioTff7b72.Td2a8ffBytesIOTb4b4b4(Te6edf3imageTb4b4b4)Tb4b4b4)
Te6edf3test_imageTff7b72.Td2a8ffverifyTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWarning: Image file at 0xTffd700%xTa5d6ff is not a valid Tffd700%sTa5d6ff image, so not changing any flash settings.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3addressTb4b4b4, Te6edf3espTff7b72.Td2a8ffCHIP_NAMETb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3image

Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_mode Tff7b72!= Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4:
Te6edf3flash_mode Tff7b72= Tb4b4b4{Ta5d6ff'Ta5d6ffqioTa5d6ff'Tb4b4b4: T79c0ff0Tb4b4b4, Ta5d6ff'Ta5d6ffqoutTa5d6ff'Tb4b4b4: T79c0ff1Tb4b4b4, Ta5d6ff'Ta5d6ffdioTa5d6ff'Tb4b4b4: T79c0ff2Tb4b4b4, Ta5d6ff'Ta5d6ffdoutTa5d6ff'Tb4b4b4: T79c0ff3Tb4b4b4}Tb4b4b4[Te6edf3argsTff7b72.Td2a8ffflash_modeTb4b4b4]

Te6edf3flash_freq Tff7b72= Te6edf3flash_size_freq Tff7b72& T79c0ff0x0F
Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_freq Tff7b72!= Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4:
Te6edf3flash_freq Tff7b72= Tb4b4b4{Ta5d6ff'Ta5d6ff40mTa5d6ff'Tb4b4b4: T79c0ff0Tb4b4b4, Ta5d6ff'Ta5d6ff26mTa5d6ff'Tb4b4b4: T79c0ff1Tb4b4b4, Ta5d6ff'Ta5d6ff20mTa5d6ff'Tb4b4b4: T79c0ff2Tb4b4b4, Ta5d6ff'Ta5d6ff80mTa5d6ff'Tb4b4b4: T79c0ff0xfTb4b4b4}Tb4b4b4[Te6edf3argsTff7b72.Td2a8ffflash_freqTb4b4b4]

Te6edf3flash_size Tff7b72= Te6edf3flash_size_freq Tff7b72& T79c0ff0xF0
Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72!= Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4:
Te6edf3flash_size Tff7b72= Te6edf3espTff7b72.Td2a8ffparse_flash_size_argTb4b4b4(Te6edf3argsTff7b72.Td2a8ffflash_sizeTb4b4b4)

Te6edf3flash_params Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ffbTa5d6ff'Ta5d6ffBBTa5d6ff'Tb4b4b4, Te6edf3flash_modeTb4b4b4, Te6edf3flash_size Tff7b72+ Te6edf3flash_freqTb4b4b4)
Tff7b72if Te6edf3flash_params Tff7b72!= Te6edf3imageTb4b4b4[T79c0ff2Tb4b4b4:T79c0ff4Tb4b4b4]Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffFlash params set to 0xTffd700%04xTa5d6ff' Tff7b72% Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff>HTa5d6ff"Tb4b4b4, Te6edf3flash_paramsTb4b4b4)Tb4b4b4)
Te6edf3image Tff7b72= Te6edf3imageTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff2Tb4b4b4] Tff7b72+ Te6edf3flash_params Tff7b72+ Te6edf3imageTb4b4b4[T79c0ff4Tb4b4b4:Tb4b4b4]
Tff7b72return Te6edf3image


Tff7b72def Td2a8ffwrite_flashTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
T8b949e# set args.compress based on default behaviour:
T8b949e# -> if either --compress or --no-compress is set, honour that
T8b949e# -> otherwise, set --compress unless --no-stub is set
Tff7b72if Te6edf3argsTff7b72.Td2a8ffcompress Tff7b72is Tff7b72None Tff7b72and Tff7b72not Te6edf3argsTff7b72.Td2a8ffno_compressTb4b4b4:
Te6edf3argsTff7b72.Td2a8ffcompress Tff7b72= Tff7b72not Te6edf3argsTff7b72.Td2a8ffno_stub

T8b949e# In case we have encrypted files to write, we first do few sanity checks before actual flash
Tff7b72if Te6edf3argsTff7b72.Td2a8ffencrypt Tff7b72or Te6edf3argsTff7b72.Td2a8ffencrypt_files Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3do_write Tff7b72= Tff7b72True

Tff7b72if Tff7b72not Te6edf3espTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Tff7b72if Te6edf3espTff7b72.Td2a8ffget_encrypted_download_disabledTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffThis chip has encrypt functionality in UART download mode disabled. Ta5d6ff"
Ta5d6ff"Ta5d6ffThis is the Flash Encryption configuration for Production mode instead of Development mode.Ta5d6ff"Tb4b4b4)

Te6edf3crypt_cfg_efuse Tff7b72= Te6edf3espTff7b72.Td2a8ffget_flash_crypt_configTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3crypt_cfg_efuse Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3crypt_cfg_efuse Tff7b72!= T79c0ff0xFTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffUnexpected FLASH_CRYPT_CONFIG value: 0xTffd700%xTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3crypt_cfg_efuseTb4b4b4)Tb4b4b4)
Te6edf3do_write Tff7b72= Tff7b72False

Te6edf3enc_key_valid Tff7b72= Te6edf3espTff7b72.Td2a8ffis_flash_encryption_key_validTb4b4b4(Tb4b4b4)

Tff7b72if Tff7b72not Te6edf3enc_key_validTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffFlash encryption key is not programmedTa5d6ff'Tb4b4b4)
Te6edf3do_write Tff7b72= Tff7b72False

T8b949e# Determine which files list contain the ones to encrypt
Te6edf3files_to_encrypt Tff7b72= Te6edf3argsTff7b72.Td2a8ffaddr_filename Tff7b72if Te6edf3argsTff7b72.Td2a8ffencrypt Tff7b72else Te6edf3argsTff7b72.Td2a8ffencrypt_files

Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfile Tff7b72in Te6edf3files_to_encryptTb4b4b4:
Tff7b72if Te6edf3address Tff7b72% Te6edf3espTff7b72.Td2a8ffFLASH_ENCRYPTED_WRITE_ALIGNTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFile Tffd700%sTa5d6ff address 0xTffd700%xTa5d6ff is not Tffd700%dTa5d6ff byte aligned, canTa5d6ff'Ta5d6fft flash encryptedTa5d6ff" Tff7b72%
Tb4b4b4(Te6edf3argfileTff7b72.Td2a8ffnameTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3espTff7b72.Td2a8ffFLASH_ENCRYPTED_WRITE_ALIGNTb4b4b4)Tb4b4b4)
Te6edf3do_write Tff7b72= Tff7b72False

Tff7b72if Tff7b72not Te6edf3do_write Tff7b72and Tff7b72not Te6edf3argsTff7b72.Td2a8ffignore_flash_encryption_efuse_settingTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffCanTa5d6ff'Ta5d6fft perform encrypted flash write, consult Flash Encryption documentation for more informationTa5d6ff"Tb4b4b4)

T8b949e# verify file sizes fit in flash
Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72!= Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4: T8b949e# TODO: check this even with 'keep'
Te6edf3flash_end Tff7b72= Te6edf3flash_size_bytesTb4b4b4(Te6edf3argsTff7b72.Td2a8ffflash_sizeTb4b4b4)
Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfile Tff7b72in Te6edf3argsTff7b72.Td2a8ffaddr_filenameTb4b4b4:
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3osTff7b72.Td2a8ffSEEK_ENDTb4b4b4)
Tff7b72if Te6edf3address Tff7b72+ Te6edf3argfileTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4) Tff7b72> Te6edf3flash_endTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffFile Tffd700%sTa5d6ff (length Tffd700%dTa5d6ff) at offset Tffd700%dTa5d6ff will not fit in Tffd700%dTa5d6ff bytes of flash. Ta5d6ff"
Ta5d6ff"Ta5d6ffUse --flash-size argument, or change flashing address.Ta5d6ff"Tb4b4b4)
Tff7b72% Tb4b4b4(Te6edf3argfileTff7b72.Td2a8ffnameTb4b4b4, Te6edf3argfileTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3addressTb4b4b4, Te6edf3flash_endTb4b4b4)Tb4b4b4)
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8fferase_allTb4b4b4:
Te6edf3erase_flashTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfile Tff7b72in Te6edf3argsTff7b72.Td2a8ffaddr_filenameTb4b4b4:
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3osTff7b72.Td2a8ffSEEK_ENDTb4b4b4)
Te6edf3write_end Tff7b72= Te6edf3address Tff7b72+ Te6edf3argfileTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3bytes_over Tff7b72= Te6edf3address Tff7b72% Te6edf3espTff7b72.Td2a8ffFLASH_SECTOR_SIZE
Tff7b72if Te6edf3bytes_over Tff7b72!= T79c0ff0Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWARNING: Flash address Tffd700{:#010x}Ta5d6ff is not aligned to a Tffd700{:#x}Ta5d6ff byte flash sector. Ta5d6ff"
Ta5d6ff"Tffd700{:#x}Ta5d6ff bytes before this address will be erased.Ta5d6ff"
Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3addressTb4b4b4, Te6edf3espTff7b72.Td2a8ffFLASH_SECTOR_SIZETb4b4b4, Te6edf3bytes_overTb4b4b4)Tb4b4b4)
T8b949e# Print the address range of to-be-erased flash memory region
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFlash will be erased from Tffd700{:#010x}Ta5d6ff to Tffd700{:#010x}Ta5d6ff...Ta5d6ff"
Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3address Tff7b72- Te6edf3bytes_overTb4b4b4, Te6edf3div_roundupTb4b4b4(Te6edf3write_endTb4b4b4, Te6edf3espTff7b72.Td2a8ffFLASH_SECTOR_SIZETb4b4b4) Tff7b72* Te6edf3espTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72- T79c0ff1Tb4b4b4)Tb4b4b4)

T8b949e""" Create a list describing all the files we have to flash. Each entry holds an "encrypt" flag
marking whether the file needs encryption or not. This list needs to be sorted.

First, append to each entry of our addr_filename list the flag args.encrypt
For example, if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")],
all_files will be [(0x1000, "partition.bin", args.encrypt), (0x8000, "bootloader", args.encrypt)],
where, of course, args.encrypt is either True or False
"""
Te6edf3all_files Tff7b72= Tb4b4b4[Tb4b4b4(Te6edf3offsTb4b4b4, Te6edf3filenameTb4b4b4, Te6edf3argsTff7b72.Td2a8ffencryptTb4b4b4) Tff7b72for Tb4b4b4(Te6edf3offsTb4b4b4, Te6edf3filenameTb4b4b4) Tff7b72in Te6edf3argsTff7b72.Td2a8ffaddr_filenameTb4b4b4]

T8b949e"""Now do the same with encrypt_files list, if defined.
In this case, the flag is True
"""
Tff7b72if Te6edf3argsTff7b72.Td2a8ffencrypt_files Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3encrypted_files_flag Tff7b72= Tb4b4b4[Tb4b4b4(Te6edf3offsTb4b4b4, Te6edf3filenameTb4b4b4, Tff7b72TrueTb4b4b4) Tff7b72for Tb4b4b4(Te6edf3offsTb4b4b4, Te6edf3filenameTb4b4b4) Tff7b72in Te6edf3argsTff7b72.Td2a8ffencrypt_filesTb4b4b4]

T8b949e# Concatenate both lists and sort them.
T8b949e# As both list are already sorted, we could simply do a merge instead,
T8b949e# but for the sake of simplicity and because the lists are very small,
T8b949e# let's use sorted.
Te6edf3all_files Tff7b72= Tffa657sortedTb4b4b4(Te6edf3all_files Tff7b72+ Te6edf3encrypted_files_flagTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)

Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfileTb4b4b4, Te6edf3encrypted Tff7b72in Te6edf3all_filesTb4b4b4:
Te6edf3compress Tff7b72= Te6edf3argsTff7b72.Td2a8ffcompress

T8b949e# Check whether we can compress the current file before flashing
Tff7b72if Te6edf3compress Tff7b72and Te6edf3encryptedTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Tffea00\nTa5d6ffWARNING: - compress and encrypt options are mutually exclusive Ta5d6ff'Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWill flash Tffd700%sTa5d6ff uncompressedTa5d6ff' Tff7b72% Te6edf3argfileTff7b72.Td2a8ffnameTb4b4b4)
Te6edf3compress Tff7b72= Tff7b72False

Tff7b72if Te6edf3argsTff7b72.Td2a8ffno_stubTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffErasing flash...Ta5d6ff'Tb4b4b4)
Te6edf3image Tff7b72= Te6edf3pad_toTb4b4b4(Te6edf3argfileTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3espTff7b72.Td2a8ffFLASH_ENCRYPTED_WRITE_ALIGN Tff7b72if Te6edf3encrypted Tff7b72else T79c0ff4Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3imageTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: File Tffd700%sTa5d6ff is emptyTa5d6ff' Tff7b72% Te6edf3argfileTff7b72.Td2a8ffnameTb4b4b4)
Tff7b72continue
Te6edf3image Tff7b72= Te6edf3_update_image_flash_paramsTb4b4b4(Te6edf3espTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3argsTb4b4b4, Te6edf3imageTb4b4b4)
Te6edf3calcmd5 Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffmd5Tb4b4b4(Te6edf3imageTb4b4b4)Tff7b72.Td2a8ffhexdigestTb4b4b4(Tb4b4b4)
Te6edf3uncsize Tff7b72= Tffa657lenTb4b4b4(Te6edf3imageTb4b4b4)
Tff7b72if Te6edf3compressTb4b4b4:
Te6edf3uncimage Tff7b72= Te6edf3image
Te6edf3image Tff7b72= Te6edf3zlibTff7b72.Td2a8ffcompressTb4b4b4(Te6edf3uncimageTb4b4b4, T79c0ff9Tb4b4b4)
T8b949e# Decompress the compressed binary a block at a time, to dynamically calculate the
T8b949e# timeout based on the real write size
Te6edf3decompress Tff7b72= Te6edf3zlibTff7b72.Td2a8ffdecompressobjTb4b4b4(Tb4b4b4)
Te6edf3blocks Tff7b72= Te6edf3espTff7b72.Td2a8ffflash_defl_beginTb4b4b4(Te6edf3uncsizeTb4b4b4, Tffa657lenTb4b4b4(Te6edf3imageTb4b4b4)Tb4b4b4, Te6edf3addressTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3blocks Tff7b72= Te6edf3espTff7b72.Td2a8ffflash_beginTb4b4b4(Te6edf3uncsizeTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3begin_rom_encryptedTff7b72=Te6edf3encryptedTb4b4b4)
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4) T8b949e# in case we need it again
Te6edf3seq Tff7b72= T79c0ff0
Te6edf3bytes_sent Tff7b72= T79c0ff0 T8b949e# bytes sent on wire
Te6edf3bytes_written Tff7b72= T79c0ff0 T8b949e# bytes written to flash
Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)

Te6edf3timeout Tff7b72= Te6edf3DEFAULT_TIMEOUT

Tff7b72while Tffa657lenTb4b4b4(Te6edf3imageTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3print_overwriteTb4b4b4(Ta5d6ff'Ta5d6ffWriting at 0xTffd700%08xTa5d6ff... (Tffd700%dTa5d6ff Tffd700%%Ta5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3address Tff7b72+ Te6edf3bytes_writtenTb4b4b4, T79c0ff100 Tff7b72* Tb4b4b4(Te6edf3seq Tff7b72+ T79c0ff1Tb4b4b4) Tff7b72/Tff7b72/ Te6edf3blocksTb4b4b4)Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3block Tff7b72= Te6edf3imageTb4b4b4[T79c0ff0Tb4b4b4:Te6edf3espTff7b72.Td2a8ffFLASH_WRITE_SIZETb4b4b4]
Tff7b72if Te6edf3compressTb4b4b4:
T8b949e# feeding each compressed block into the decompressor lets us see block-by-block how much will be written
Te6edf3block_uncompressed Tff7b72= Tffa657lenTb4b4b4(Te6edf3decompressTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3blockTb4b4b4)Tb4b4b4)
Te6edf3bytes_written Tff7b72+Tff7b72= Te6edf3block_uncompressed
Te6edf3block_timeout Tff7b72= Tffa657maxTb4b4b4(Te6edf3DEFAULT_TIMEOUTTb4b4b4, Te6edf3timeout_per_mbTb4b4b4(Te6edf3ERASE_WRITE_TIMEOUT_PER_MBTb4b4b4, Te6edf3block_uncompressedTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3espTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3timeout Tff7b72= Te6edf3block_timeout T8b949e# ROM code writes block to flash before ACKing
Te6edf3espTff7b72.Td2a8ffflash_defl_blockTb4b4b4(Te6edf3blockTb4b4b4, Te6edf3seqTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72if Te6edf3espTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3timeout Tff7b72= Te6edf3block_timeout T8b949e# Stub ACKs when block is received, then writes to flash while receiving the block after it
Tff7b72elseTb4b4b4:
T8b949e# Pad the last block
Te6edf3block Tff7b72= Te6edf3block Tff7b72+ Ta5d6ffbTa5d6ff'Tffea00\xffTa5d6ff' Tff7b72* Tb4b4b4(Te6edf3espTff7b72.Td2a8ffFLASH_WRITE_SIZE Tff7b72- Tffa657lenTb4b4b4(Te6edf3blockTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3encryptedTb4b4b4:
Te6edf3espTff7b72.Td2a8ffflash_encrypt_blockTb4b4b4(Te6edf3blockTb4b4b4, Te6edf3seqTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3espTff7b72.Td2a8ffflash_blockTb4b4b4(Te6edf3blockTb4b4b4, Te6edf3seqTb4b4b4)
Te6edf3bytes_written Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3blockTb4b4b4)
Te6edf3bytes_sent Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3blockTb4b4b4)
Te6edf3image Tff7b72= Te6edf3imageTb4b4b4[Te6edf3espTff7b72.Td2a8ffFLASH_WRITE_SIZETb4b4b4:Tb4b4b4]
Te6edf3seq Tff7b72+Tff7b72= T79c0ff1

Tff7b72if Te6edf3espTff7b72.Td2a8ffIS_STUBTb4b4b4:
T8b949e# Stub only writes each block to flash after 'ack'ing the receive, so do a final dummy operation which will
T8b949e# not be 'ack'ed until the last block has actually been written out to flash
Te6edf3espTff7b72.Td2a8ffread_regTb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffCHIP_DETECT_MAGIC_REG_ADDRTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)

Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3t
Te6edf3speed_msg Tff7b72= Ta5d6ff"Ta5d6ff"
Tff7b72if Te6edf3compressTb4b4b4:
Tff7b72if Te6edf3t Tff7b72> T79c0ff0.0Tb4b4b4:
Te6edf3speed_msg Tff7b72= Ta5d6ff"Ta5d6ff (effective Tffd700%.1fTa5d6ff kbit/s)Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3uncsize Tff7b72/ Te6edf3t Tff7b72* T79c0ff8 Tff7b72/ T79c0ff1000Tb4b4b4)
Te6edf3print_overwriteTb4b4b4(Ta5d6ff'Ta5d6ffWrote Tffd700%dTa5d6ff bytes (Tffd700%dTa5d6ff compressed) at 0xTffd700%08xTa5d6ff in Tffd700%.1fTa5d6ff secondsTffd700%sTa5d6ff...Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3uncsizeTb4b4b4,
Te6edf3bytes_sentTb4b4b4,
Te6edf3addressTb4b4b4, Te6edf3tTb4b4b4, Te6edf3speed_msgTb4b4b4)Tb4b4b4, Te6edf3last_lineTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72if Te6edf3t Tff7b72> T79c0ff0.0Tb4b4b4:
Te6edf3speed_msg Tff7b72= Ta5d6ff"Ta5d6ff (Tffd700%.1fTa5d6ff kbit/s)Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3bytes_written Tff7b72/ Te6edf3t Tff7b72* T79c0ff8 Tff7b72/ T79c0ff1000Tb4b4b4)
Te6edf3print_overwriteTb4b4b4(Ta5d6ff'Ta5d6ffWrote Tffd700%dTa5d6ff bytes at 0xTffd700%08xTa5d6ff in Tffd700%.1fTa5d6ff secondsTffd700%sTa5d6ff...Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3bytes_writtenTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3tTb4b4b4, Te6edf3speed_msgTb4b4b4)Tb4b4b4, Te6edf3last_lineTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72if Tff7b72not Te6edf3encrypted Tff7b72and Tff7b72not Te6edf3espTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3res Tff7b72= Te6edf3espTff7b72.Td2a8ffflash_md5sumTb4b4b4(Te6edf3addressTb4b4b4, Te6edf3uncsizeTb4b4b4)
Tff7b72if Te6edf3res Tff7b72!= Te6edf3calcmd5Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffFile md5: Tffd700%sTa5d6ff' Tff7b72% Te6edf3calcmd5Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffFlash md5: Tffd700%sTa5d6ff' Tff7b72% Te6edf3resTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffMD5 of 0xFF is Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3hashlibTff7b72.Td2a8ffmd5Tb4b4b4(Ta5d6ffbTa5d6ff'Tffea00\xFFTa5d6ff' Tff7b72* Te6edf3uncsizeTb4b4b4)Tff7b72.Td2a8ffhexdigestTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffMD5 of file does not match data in flash!Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffHash of data verified.Ta5d6ff'Tb4b4b4)
Tff7b72except Te6edf3NotImplementedInROMErrorTb4b4b4:
Tff7b72pass

Tffa657printTb4b4b4(Ta5d6ff'Tffea00\nTa5d6ffLeaving...Ta5d6ff'Tb4b4b4)

Tff7b72if Te6edf3espTff7b72.Td2a8ffIS_STUBTb4b4b4:
T8b949e# skip sending flash_finish to ROM loader here,
T8b949e# as it causes the loader to exit and run user code
Te6edf3espTff7b72.Td2a8ffflash_beginTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)

T8b949e# Get the "encrypted" flag for the last file flashed
T8b949e# Note: all_files list contains triplets like:
T8b949e# (address: Integer, filename: String, encrypted: Boolean)
Te6edf3last_file_encrypted Tff7b72= Te6edf3all_filesTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4[T79c0ff2Tb4b4b4]

T8b949e# Check whether the last file flashed was compressed or not
Tff7b72if Te6edf3argsTff7b72.Td2a8ffcompress Tff7b72and Tff7b72not Te6edf3last_file_encryptedTb4b4b4:
Te6edf3espTff7b72.Td2a8ffflash_defl_finishTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3espTff7b72.Td2a8ffflash_finishTb4b4b4(Tff7b72FalseTb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8ffverifyTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffVerifying just-written flash...Ta5d6ff'Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff(This option is deprecated, flash contents are now always read back after flashing.)Ta5d6ff'Tb4b4b4)
T8b949e# If some encrypted files have been flashed print a warning saying that we won't check them
Tff7b72if Te6edf3argsTff7b72.Td2a8ffencrypt Tff7b72or Te6edf3argsTff7b72.Td2a8ffencrypt_files Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWARNING: - cannot verify encrypted files, they will be ignoredTa5d6ff'Tb4b4b4)
T8b949e# Call verify_flash function only if there at least one non-encrypted file flashed
Tff7b72if Tff7b72not Te6edf3argsTff7b72.Td2a8ffencryptTb4b4b4:
Te6edf3verify_flashTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)


Tff7b72def Td2a8ffimage_infoTb4b4b4(Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3LoadFirmwareImageTb4b4b4(Te6edf3argsTff7b72.Td2a8ffchipTb4b4b4, Te6edf3argsTff7b72.Td2a8fffilenameTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffImage version: Tffd700%dTa5d6ff' Tff7b72% Te6edf3imageTff7b72.Td2a8ffversionTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffEntry point: Tffd700%08xTa5d6ff' Tff7b72% Te6edf3imageTff7b72.Td2a8ffentrypoint Tff7b72if Te6edf3imageTff7b72.Td2a8ffentrypoint Tff7b72!= T79c0ff0 Tff7b72else Ta5d6ff'Ta5d6ffEntry point not setTa5d6ff'Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Tffd700%dTa5d6ff segmentsTa5d6ff' Tff7b72% Tffa657lenTb4b4b4(Te6edf3imageTff7b72.Td2a8ffsegmentsTb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4)
Te6edf3idx Tff7b72= T79c0ff0
Tff7b72for Te6edf3seg Tff7b72in Te6edf3imageTff7b72.Td2a8ffsegmentsTb4b4b4:
Te6edf3idx Tff7b72+Tff7b72= T79c0ff1
Te6edf3segs Tff7b72= Te6edf3segTff7b72.Td2a8ffget_memory_typeTb4b4b4(Te6edf3imageTb4b4b4)
Te6edf3seg_name Tff7b72= Ta5d6ff"Ta5d6ff,Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3segsTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffSegment Tffd700%dTa5d6ff: Tffd700%rTa5d6ff [Tffd700%sTa5d6ff]Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3idxTb4b4b4, Te6edf3segTb4b4b4, Te6edf3seg_nameTb4b4b4)Tb4b4b4)
Te6edf3calc_checksum Tff7b72= Te6edf3imageTff7b72.Td2a8ffcalculate_checksumTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffChecksum: Tffd700%02xTa5d6ff (Tffd700%sTa5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3imageTff7b72.Td2a8ffchecksumTb4b4b4,
Ta5d6ff'Ta5d6ffvalidTa5d6ff' Tff7b72if Te6edf3imageTff7b72.Td2a8ffchecksum Tff7b72== Te6edf3calc_checksum Tff7b72else Ta5d6ff'Ta5d6ffinvalid - calculated Tffd700%02xTa5d6ff' Tff7b72% Te6edf3calc_checksumTb4b4b4)Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3digest_msg Tff7b72= Ta5d6ff'Ta5d6ffNot appendedTa5d6ff'
Tff7b72if Te6edf3imageTff7b72.Td2a8ffappend_digestTb4b4b4:
Te6edf3is_valid Tff7b72= Te6edf3imageTff7b72.Td2a8ffstored_digest Tff7b72== Te6edf3imageTff7b72.Td2a8ffcalc_digest
Te6edf3digest_msg Tff7b72= Ta5d6ff"Tffd700%sTa5d6ff (Tffd700%sTa5d6ff)Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3hexifyTb4b4b4(Te6edf3imageTff7b72.Td2a8ffcalc_digestTb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffvalidTa5d6ff" Tff7b72if Te6edf3is_valid Tff7b72else Ta5d6ff"Ta5d6ffinvalidTa5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffValidation Hash: Tffd700%sTa5d6ff' Tff7b72% Te6edf3digest_msgTb4b4b4)
Tff7b72except Tf85149AttributeErrorTb4b4b4:
Tff7b72pass T8b949e# ESP8266 image has no append_digest field


Tff7b72def Td2a8ffmake_imageTb4b4b4(Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP8266ROMFirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3argsTff7b72.Td2a8ffsegfileTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffNo segments specifiedTa5d6ff'Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3argsTff7b72.Td2a8ffsegfileTb4b4b4) Tff7b72!= Tffa657lenTb4b4b4(Te6edf3argsTff7b72.Td2a8ffsegaddrTb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff'Ta5d6ffNumber of specified files does not match number of specified addressesTa5d6ff'Tb4b4b4)
Tff7b72for Tb4b4b4(Te6edf3segTb4b4b4, Te6edf3addrTb4b4b4) Tff7b72in Tffa657zipTb4b4b4(Te6edf3argsTff7b72.Td2a8ffsegfileTb4b4b4, Te6edf3argsTff7b72.Td2a8ffsegaddrTb4b4b4)Tb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3segTb4b4b4, Ta5d6ff'Ta5d6ffrbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3data Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Te6edf3imageTff7b72.Td2a8ffsegmentsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3ImageSegmentTb4b4b4(Te6edf3addrTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4)
Te6edf3imageTff7b72.Td2a8ffentrypoint Tff7b72= Te6edf3argsTff7b72.Td2a8ffentrypoint
Te6edf3imageTff7b72.Td2a8ffsaveTb4b4b4(Te6edf3argsTff7b72.Td2a8ffoutputTb4b4b4)


Tff7b72def Td2a8ffelf2imageTb4b4b4(Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3e Tff7b72= Te6edf3ELFFileTb4b4b4(Te6edf3argsTff7b72.Td2a8ffinputTb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffautoTa5d6ff'Tb4b4b4: T8b949e# Default to ESP8266 for backwards compatibility
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffCreating image for ESP8266...Ta5d6ff"Tb4b4b4)
Te6edf3argsTff7b72.Td2a8ffchip Tff7b72= Ta5d6ff'Ta5d6ffesp8266Ta5d6ff'

Tff7b72if Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffesp32Ta5d6ff'Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP32FirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffsecure_padTb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff1Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffsecure_pad_v2Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff2Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffesp32s2Ta5d6ff'Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP32S2FirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffsecure_pad_v2Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff2Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffesp32s3beta2Ta5d6ff'Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP32S3BETA2FirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffsecure_pad_v2Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff2Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffesp32s3beta3Ta5d6ff'Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP32S3BETA3FirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffsecure_pad_v2Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff2Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffesp32c3Ta5d6ff'Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP32C3FirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffsecure_pad_v2Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff2Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffchip Tff7b72== Ta5d6ff'Ta5d6ffesp32c6betaTa5d6ff'Tb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP32C6BETAFirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffsecure_pad_v2Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffsecure_pad Tff7b72= Ta5d6ff'Ta5d6ff2Ta5d6ff'
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffversion Tff7b72== Ta5d6ff'Ta5d6ff1Ta5d6ff'Tb4b4b4: T8b949e# ESP8266
Te6edf3image Tff7b72= Te6edf3ESP8266ROMFirmwareImageTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3image Tff7b72= Te6edf3ESP8266V2FirmwareImageTb4b4b4(Tb4b4b4)
Te6edf3imageTff7b72.Td2a8ffentrypoint Tff7b72= Te6edf3eTff7b72.Td2a8ffentrypoint
Te6edf3imageTff7b72.Td2a8ffflash_mode Tff7b72= Tb4b4b4{Ta5d6ff'Ta5d6ffqioTa5d6ff'Tb4b4b4: T79c0ff0Tb4b4b4, Ta5d6ff'Ta5d6ffqoutTa5d6ff'Tb4b4b4: T79c0ff1Tb4b4b4, Ta5d6ff'Ta5d6ffdioTa5d6ff'Tb4b4b4: T79c0ff2Tb4b4b4, Ta5d6ff'Ta5d6ffdoutTa5d6ff'Tb4b4b4: T79c0ff3Tb4b4b4}Tb4b4b4[Te6edf3argsTff7b72.Td2a8ffflash_modeTb4b4b4]

Tff7b72if Te6edf3argsTff7b72.Td2a8ffchip Tff7b72!= Ta5d6ff'Ta5d6ffesp8266Ta5d6ff'Tb4b4b4:
Te6edf3imageTff7b72.Td2a8ffmin_rev Tff7b72= Tffa657intTb4b4b4(Te6edf3argsTff7b72.Td2a8ffmin_revTb4b4b4)

T8b949e# ELFSection is a subclass of ImageSegment, so can use interchangeably
Te6edf3imageTff7b72.Td2a8ffsegments Tff7b72= Te6edf3eTff7b72.Td2a8ffsegments Tff7b72if Te6edf3argsTff7b72.Td2a8ffuse_segments Tff7b72else Te6edf3eTff7b72.Td2a8ffsections

Te6edf3imageTff7b72.Td2a8ffflash_size_freq Tff7b72= Te6edf3imageTff7b72.Td2a8ffROM_LOADERTff7b72.Td2a8ffFLASH_SIZESTb4b4b4[Te6edf3argsTff7b72.Td2a8ffflash_sizeTb4b4b4]
Te6edf3imageTff7b72.Td2a8ffflash_size_freq Tff7b72+Tff7b72= Tb4b4b4{Ta5d6ff'Ta5d6ff40mTa5d6ff'Tb4b4b4: T79c0ff0Tb4b4b4, Ta5d6ff'Ta5d6ff26mTa5d6ff'Tb4b4b4: T79c0ff1Tb4b4b4, Ta5d6ff'Ta5d6ff20mTa5d6ff'Tb4b4b4: T79c0ff2Tb4b4b4, Ta5d6ff'Ta5d6ff80mTa5d6ff'Tb4b4b4: T79c0ff0xfTb4b4b4}Tb4b4b4[Te6edf3argsTff7b72.Td2a8ffflash_freqTb4b4b4]

Tff7b72if Te6edf3argsTff7b72.Td2a8ffelf_sha256_offsetTb4b4b4:
Te6edf3imageTff7b72.Td2a8ffelf_sha256 Tff7b72= Te6edf3eTff7b72.Td2a8ffsha256Tb4b4b4(Tb4b4b4)
Te6edf3imageTff7b72.Td2a8ffelf_sha256_offset Tff7b72= Te6edf3argsTff7b72.Td2a8ffelf_sha256_offset

Te6edf3before Tff7b72= Tffa657lenTb4b4b4(Te6edf3imageTff7b72.Td2a8ffsegmentsTb4b4b4)
Te6edf3imageTff7b72.Td2a8ffmerge_adjacent_segmentsTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3imageTff7b72.Td2a8ffsegmentsTb4b4b4) Tff7b72!= Te6edf3beforeTb4b4b4:
Te6edf3delta Tff7b72= Te6edf3before Tff7b72- Tffa657lenTb4b4b4(Te6edf3imageTff7b72.Td2a8ffsegmentsTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffMerged Tffd700%dTa5d6ff ELF sectionTffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3deltaTb4b4b4, Ta5d6ff"Ta5d6ffsTa5d6ff" Tff7b72if Te6edf3delta Tff7b72> T79c0ff1 Tff7b72else Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4)

Te6edf3imageTff7b72.Td2a8ffverifyTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8ffoutput Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3argsTff7b72.Td2a8ffoutput Tff7b72= Te6edf3imageTff7b72.Td2a8ffdefault_output_nameTb4b4b4(Te6edf3argsTff7b72.Td2a8ffinputTb4b4b4)
Te6edf3imageTff7b72.Td2a8ffsaveTb4b4b4(Te6edf3argsTff7b72.Td2a8ffoutputTb4b4b4)


Tff7b72def Td2a8ffread_macTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3mac Tff7b72= Te6edf3espTff7b72.Td2a8ffread_macTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffprint_macTb4b4b4(Te6edf3labelTb4b4b4, Te6edf3macTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Tffd700%sTa5d6ff: Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3labelTb4b4b4, Ta5d6ff'Ta5d6ff:Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Tffa657mapTb4b4b4(Tff7b72lambda Te6edf3xTb4b4b4: Ta5d6ff'Tffd700%02xTa5d6ff' Tff7b72% Te6edf3xTb4b4b4, Te6edf3macTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3print_macTb4b4b4(Ta5d6ff"Ta5d6ffMACTa5d6ff"Tb4b4b4, Te6edf3macTb4b4b4)


Tff7b72def Td2a8ffchip_idTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3chipid Tff7b72= Te6edf3espTff7b72.Td2a8ffchip_idTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffChip ID: 0xTffd700%08xTa5d6ff' Tff7b72% Te6edf3chipidTb4b4b4)
Tff7b72except Te6edf3NotSupportedErrorTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffWarning: Tffd700%sTa5d6ff has no Chip ID. Reading MAC instead.Ta5d6ff' Tff7b72% Te6edf3espTff7b72.Td2a8ffCHIP_NAMETb4b4b4)
Te6edf3read_macTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)


Tff7b72def Td2a8fferase_flashTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffErasing flash (this may take a while)...Ta5d6ff'Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3espTff7b72.Td2a8fferase_flashTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffChip erase completed successfully in Tffd700%.1fTa5d6ffsTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3tTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8fferase_regionTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffErasing region (may be slow depending on size)...Ta5d6ff'Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3espTff7b72.Td2a8fferase_regionTb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4, Te6edf3argsTff7b72.Td2a8ffsizeTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffErase completed successfully in Tffd700%.1fTa5d6ff seconds.Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3tTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffrunTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3espTff7b72.Td2a8ffrunTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8ffflash_idTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3flash_id Tff7b72= Te6edf3espTff7b72.Td2a8ffflash_idTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffManufacturer: Tffd700%02xTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3flash_id Tff7b72& T79c0ff0xffTb4b4b4)Tb4b4b4)
Te6edf3flid_lowbyte Tff7b72= Tb4b4b4(Te6edf3flash_id Tff7b72>> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0xFF
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffDevice: Tffd700%02xTffd700%02xTa5d6ff' Tff7b72% Tb4b4b4(Tb4b4b4(Te6edf3flash_id Tff7b72>> T79c0ff8Tb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4, Te6edf3flid_lowbyteTb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffDetected flash size: Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3DETECTED_FLASH_SIZESTff7b72.Td2a8ffgetTb4b4b4(Te6edf3flid_lowbyteTb4b4b4, Ta5d6ff"Ta5d6ffUnknownTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffread_flashTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3argsTff7b72.Td2a8ffno_progressTb4b4b4:
Te6edf3flash_progress Tff7b72= Tff7b72None
Tff7b72elseTb4b4b4:
Tff7b72def Td2a8ffflash_progressTb4b4b4(Te6edf3progressTb4b4b4, Te6edf3lengthTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff'Tffd700%dTa5d6ff (Tffd700%dTa5d6ff Tffd700%%Ta5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3progressTb4b4b4, Te6edf3progress Tff7b72* T79c0ff100.0 Tff7b72/ Te6edf3lengthTb4b4b4)
Te6edf3padding Tff7b72= Ta5d6ff'Tffea00\bTa5d6ff' Tff7b72* Tffa657lenTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3progress Tff7b72== Te6edf3lengthTb4b4b4:
Te6edf3padding Tff7b72= Ta5d6ff'Tffea00\nTa5d6ff'
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3msg Tff7b72+ Te6edf3paddingTb4b4b4)
Te6edf3sysTff7b72.Td2a8ffstdoutTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3data Tff7b72= Te6edf3espTff7b72.Td2a8ffread_flashTb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4, Te6edf3argsTff7b72.Td2a8ffsizeTb4b4b4, Te6edf3flash_progressTb4b4b4)
Te6edf3t Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3t
Te6edf3print_overwriteTb4b4b4(Ta5d6ff'Ta5d6ffRead Tffd700%dTa5d6ff bytes at 0xTffd700%xTa5d6ff in Tffd700%.1fTa5d6ff seconds (Tffd700%.1fTa5d6ff kbit/s)...Ta5d6ff'
Tff7b72% Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4, Te6edf3argsTff7b72.Td2a8ffaddressTb4b4b4, Te6edf3tTb4b4b4, Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72/ Te6edf3t Tff7b72* T79c0ff8 Tff7b72/ T79c0ff1000Tb4b4b4)Tb4b4b4, Te6edf3last_lineTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3argsTff7b72.Td2a8fffilenameTb4b4b4, Ta5d6ff'Ta5d6ffwbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3dataTb4b4b4)


Tff7b72def Td2a8ffverify_flashTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3differences Tff7b72= Tff7b72False

Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfile Tff7b72in Te6edf3argsTff7b72.Td2a8ffaddr_filenameTb4b4b4:
Te6edf3image Tff7b72= Te6edf3pad_toTb4b4b4(Te6edf3argfileTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff4Tb4b4b4)
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4) T8b949e# rewind in case we need it again

Te6edf3image Tff7b72= Te6edf3_update_image_flash_paramsTb4b4b4(Te6edf3espTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3argsTb4b4b4, Te6edf3imageTb4b4b4)

Te6edf3image_size Tff7b72= Tffa657lenTb4b4b4(Te6edf3imageTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffVerifying 0xTffd700%xTa5d6ff (Tffd700%dTa5d6ff) bytes @ 0xTffd700%08xTa5d6ff in flash against Tffd700%sTa5d6ff...Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3image_sizeTb4b4b4, Te6edf3image_sizeTb4b4b4, Te6edf3addressTb4b4b4, Te6edf3argfileTff7b72.Td2a8ffnameTb4b4b4)Tb4b4b4)
T8b949e# Try digest first, only read if there are differences.
Te6edf3digest Tff7b72= Te6edf3espTff7b72.Td2a8ffflash_md5sumTb4b4b4(Te6edf3addressTb4b4b4, Te6edf3image_sizeTb4b4b4)
Te6edf3expected_digest Tff7b72= Te6edf3hashlibTff7b72.Td2a8ffmd5Tb4b4b4(Te6edf3imageTb4b4b4)Tff7b72.Td2a8ffhexdigestTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3digest Tff7b72== Te6edf3expected_digestTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff-- verify OK (digest matched)Ta5d6ff'Tb4b4b4)
Tff7b72continue
Tff7b72elseTb4b4b4:
Te6edf3differences Tff7b72= Tff7b72True
Tff7b72if Tffa657getattrTb4b4b4(Te6edf3argsTb4b4b4, Ta5d6ff'Ta5d6ffdiffTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffnoTa5d6ff'Tb4b4b4) Tff7b72!= Ta5d6ff'Ta5d6ffyesTa5d6ff'Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff-- verify FAILED (digest mismatch)Ta5d6ff'Tb4b4b4)
Tff7b72continue

Te6edf3flash Tff7b72= Te6edf3espTff7b72.Td2a8ffread_flashTb4b4b4(Te6edf3addressTb4b4b4, Te6edf3image_sizeTb4b4b4)
Tff7b72assert Te6edf3flash Tff7b72!= Te6edf3image
Te6edf3diff Tff7b72= Tb4b4b4[Te6edf3i Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3image_sizeTb4b4b4) Tff7b72if Te6edf3flashTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!= Te6edf3imageTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4]
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff-- verify FAILED: Tffd700%dTa5d6ff differences, first @ 0xTffd700%08xTa5d6ff' Tff7b72% Tb4b4b4(Tffa657lenTb4b4b4(Te6edf3diffTb4b4b4)Tb4b4b4, Te6edf3address Tff7b72+ Te6edf3diffTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3d Tff7b72in Te6edf3diffTb4b4b4:
Te6edf3flash_byte Tff7b72= Te6edf3flashTb4b4b4[Te6edf3dTb4b4b4]
Te6edf3image_byte Tff7b72= Te6edf3imageTb4b4b4[Te6edf3dTb4b4b4]
Tff7b72if Te6edf3PYTHON2Tb4b4b4:
Te6edf3flash_byte Tff7b72= Tffa657ordTb4b4b4(Te6edf3flash_byteTb4b4b4)
Te6edf3image_byte Tff7b72= Tffa657ordTb4b4b4(Te6edf3image_byteTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ff Tffd700%08xTa5d6ff Tffd700%02xTa5d6ff Tffd700%02xTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3address Tff7b72+ Te6edf3dTb4b4b4, Te6edf3flash_byteTb4b4b4, Te6edf3image_byteTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3differencesTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffVerify failed.Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffread_flash_statusTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffStatus value: 0xTffd700%04xTa5d6ff' Tff7b72% Te6edf3espTff7b72.Td2a8ffread_statusTb4b4b4(Te6edf3argsTff7b72.Td2a8ffbytesTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffwrite_flash_statusTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3fmt Tff7b72= Ta5d6ff"Ta5d6ff0xTffd700%%Ta5d6ff0Tffd700%dTa5d6ffxTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3argsTff7b72.Td2a8ffbytes Tff7b72* T79c0ff2Tb4b4b4)
Te6edf3argsTff7b72.Td2a8ffvalue Tff7b72= Te6edf3argsTff7b72.Td2a8ffvalue Tff7b72& Tb4b4b4(Tb4b4b4(T79c0ff1 Tff7b72<< Tb4b4b4(Te6edf3argsTff7b72.Td2a8ffbytes Tff7b72* T79c0ff8Tb4b4b4)Tb4b4b4) Tff7b72- T79c0ff1Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4(Ta5d6ff'Ta5d6ffInitial flash status: Ta5d6ff' Tff7b72+ Te6edf3fmtTb4b4b4) Tff7b72% Te6edf3espTff7b72.Td2a8ffread_statusTb4b4b4(Te6edf3argsTff7b72.Td2a8ffbytesTb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4(Ta5d6ff'Ta5d6ffSetting flash status: Ta5d6ff' Tff7b72+ Te6edf3fmtTb4b4b4) Tff7b72% Te6edf3argsTff7b72.Td2a8ffvalueTb4b4b4)
Te6edf3espTff7b72.Td2a8ffwrite_statusTb4b4b4(Te6edf3argsTff7b72.Td2a8ffvalueTb4b4b4, Te6edf3argsTff7b72.Td2a8ffbytesTb4b4b4, Te6edf3argsTff7b72.Td2a8ffnon_volatileTb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4(Ta5d6ff'Ta5d6ffAfter flash status: Ta5d6ff' Tff7b72+ Te6edf3fmtTb4b4b4) Tff7b72% Te6edf3espTff7b72.Td2a8ffread_statusTb4b4b4(Te6edf3argsTff7b72.Td2a8ffbytesTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffget_security_infoTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)Tb4b4b4:
Tb4b4b4(Te6edf3flagsTb4b4b4, Te6edf3flash_crypt_cntTb4b4b4, Te6edf3key_purposesTb4b4b4) Tff7b72= Te6edf3espTff7b72.Td2a8ffget_security_infoTb4b4b4(Tb4b4b4)
T8b949e# TODO: better display
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffFlags: 0xTffd700%08xTa5d6ff (Tffd700%sTa5d6ff)Ta5d6ff' Tff7b72% Tb4b4b4(Te6edf3flagsTb4b4b4, Tffa657binTb4b4b4(Te6edf3flagsTb4b4b4)Tb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffFlash_Crypt_Cnt: 0xTffd700%xTa5d6ff' Tff7b72% Te6edf3flash_crypt_cntTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffKey_Purposes: Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3key_purposesTb4b4b4,Tb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffmerge_binTb4b4b4(Te6edf3argsTb4b4b4)Tb4b4b4:
Te6edf3chip_class Tff7b72= Te6edf3_chip_to_rom_loaderTb4b4b4(Te6edf3argsTff7b72.Td2a8ffchipTb4b4b4)

T8b949e# sort the files by offset. The AddrFilenamePairAction has already checked for overlap
Te6edf3input_files Tff7b72= Tffa657sortedTb4b4b4(Te6edf3argsTff7b72.Td2a8ffaddr_filenameTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3input_filesTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo input files specifiedTa5d6ff"Tb4b4b4)
Te6edf3first_addr Tff7b72= Te6edf3input_filesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72if Te6edf3first_addr Tff7b72< Te6edf3argsTff7b72.Td2a8fftarget_offsetTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffOutput file target offset is 0xTffd700%xTa5d6ff. Input file offset 0xTffd700%xTa5d6ff is before this.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3argsTff7b72.Td2a8fftarget_offsetTb4b4b4, Te6edf3first_addrTb4b4b4)Tb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8ffformat Tff7b72!= Ta5d6ff'Ta5d6ffrawTa5d6ff'Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffThis version of esptool only supports the Ta5d6ff'Ta5d6ffrawTa5d6ff'Ta5d6ff output formatTa5d6ff"Tb4b4b4)

Tff7b72with Tffa657openTb4b4b4(Te6edf3argsTff7b72.Td2a8ffoutputTb4b4b4, Ta5d6ff'Ta5d6ffwbTa5d6ff'Tb4b4b4) Tff7b72as Te6edf3ofTb4b4b4:
Tff7b72def Td2a8ffpad_toTb4b4b4(Te6edf3flash_offsTb4b4b4)Tb4b4b4:
T8b949e# account for output file offset if there is any
Te6edf3ofTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ffbTa5d6ff'Tffea00\xFFTa5d6ff' Tff7b72* Tb4b4b4(Te6edf3flash_offs Tff7b72- Te6edf3argsTff7b72.Td2a8fftarget_offset Tff7b72- Te6edf3ofTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3addrTb4b4b4, Te6edf3argfile Tff7b72in Te6edf3input_filesTb4b4b4:
Te6edf3pad_toTb4b4b4(Te6edf3addrTb4b4b4)
Te6edf3image Tff7b72= Te6edf3argfileTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Te6edf3image Tff7b72= Te6edf3_update_image_flash_paramsTb4b4b4(Te6edf3chip_classTb4b4b4, Te6edf3addrTb4b4b4, Te6edf3argsTb4b4b4, Te6edf3imageTb4b4b4)
Te6edf3ofTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3imageTb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8fffill_flash_sizeTb4b4b4:
Te6edf3pad_toTb4b4b4(Te6edf3flash_size_bytesTb4b4b4(Te6edf3argsTff7b72.Td2a8fffill_flash_sizeTb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWrote 0xTffd700%xTa5d6ff bytes to file Tffd700%sTa5d6ff, ready to flash to offset 0xTffd700%xTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3ofTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3argsTff7b72.Td2a8ffoutputTb4b4b4, Te6edf3argsTff7b72.Td2a8fftarget_offsetTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffversionTb4b4b4(Te6edf3argsTb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Te6edf3__version__Tb4b4b4)

T8b949e#
T8b949e# End of operations functions
T8b949e#


Tff7b72def Td2a8ffmainTb4b4b4(Te6edf3argvTff7b72=Tff7b72NoneTb4b4b4, Te6edf3espTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""
Main function for esptool

argv - Optional override for default arguments parsing (that uses sys.argv), can be a list of custom arguments
as strings. Arguments and their values need to be added as individual items to the list e.g. "-b 115200" thus
becomes ['-b', '115200'].

esp - Optional override of the connected device previously returned by get_default_connected_device()
"""

Te6edf3external_esp Tff7b72= Te6edf3esp Tff7b72is Tff7b72not Tff7b72None

Te6edf3parser Tff7b72= Te6edf3argparseTff7b72.Td2a8ffArgumentParserTb4b4b4(Te6edf3descriptionTff7b72=Ta5d6ff'Ta5d6ffesptool.py vTffd700%sTa5d6ff - ESP8266 ROM Bootloader UtilityTa5d6ff' Tff7b72% Te6edf3__version__Tb4b4b4, Te6edf3progTff7b72=Ta5d6ff'Ta5d6ffesptoolTa5d6ff'Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--chipTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-cTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffTarget chip typeTa5d6ff'Tb4b4b4,
Tffa657typeTff7b72=Tff7b72lambda Te6edf3cTb4b4b4: Te6edf3cTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff'Ta5d6ff-Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff'Tb4b4b4)Tb4b4b4, T8b949e# support ESP32-S2, etc.
Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff'Ta5d6ffautoTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp8266Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp32Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp32s2Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp32s3beta2Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp32s3beta3Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp32c3Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffesp32c6betaTa5d6ff'Tb4b4b4]Tb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_CHIPTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffautoTa5d6ff'Tb4b4b4)Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--portTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-pTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSerial port deviceTa5d6ff'Tb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_PORTTa5d6ff'Tb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--baudTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-bTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSerial port baud rate used when flashing/readingTa5d6ff'Tb4b4b4,
Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_BAUDTa5d6ff'Tb4b4b4, Te6edf3ESPLoaderTff7b72.Td2a8ffESP_ROM_BAUDTb4b4b4)Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--beforeTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffWhat to do before connecting to the chipTa5d6ff'Tb4b4b4,
Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff'Ta5d6ffdefault_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffusb_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffno_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffno_reset_no_syncTa5d6ff'Tb4b4b4]Tb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_BEFORETa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffdefault_resetTa5d6ff'Tb4b4b4)Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--afterTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-aTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffWhat to do after esptool.py is finishedTa5d6ff'Tb4b4b4,
Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff'Ta5d6ffhard_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffsoft_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffno_resetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffno_reset_stubTa5d6ff'Tb4b4b4]Tb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_AFTERTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffhard_resetTa5d6ff'Tb4b4b4)Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--no-stubTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffDisable launching the flasher stub, only talk to ROM bootloader. Some features will not be available.Ta5d6ff"Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--traceTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-tTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffEnable trace-level output of esptool.py interactions.Ta5d6ff"Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--override-vddsdioTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffOverride ESP32 VDDSDIO internal voltage regulator (use with care)Ta5d6ff"Tb4b4b4,
Te6edf3choicesTff7b72=Te6edf3ESP32ROMTff7b72.Td2a8ffOVERRIDE_VDDSDIO_CHOICESTb4b4b4,
Te6edf3nargsTff7b72=Ta5d6ff'Ta5d6ff?Ta5d6ff'Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff'Ta5d6ff--connect-attemptsTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Tb4b4b4(Ta5d6ff'Ta5d6ffNumber of attempts to connect, negative or 0 for infinite. Ta5d6ff'
Ta5d6ff'Ta5d6ffDefault: Tffd700%dTa5d6ff.Ta5d6ff' Tff7b72% Te6edf3DEFAULT_CONNECT_ATTEMPTSTb4b4b4)Tb4b4b4,
Tffa657typeTff7b72=Tffa657intTb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_CONNECT_ATTEMPTSTa5d6ff'Tb4b4b4, Te6edf3DEFAULT_CONNECT_ATTEMPTSTb4b4b4)Tb4b4b4)

Te6edf3subparsers Tff7b72= Te6edf3parserTff7b72.Td2a8ffadd_subparsersTb4b4b4(
Te6edf3destTff7b72=Ta5d6ff'Ta5d6ffoperationTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRun esptool Tffd700{command}Ta5d6ff -h for additional helpTa5d6ff'Tb4b4b4)

Tff7b72def Td2a8ffadd_spi_connection_argTb4b4b4(Te6edf3parentTb4b4b4)Tb4b4b4:
Te6edf3parentTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--spi-connectionTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-scTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffESP32-only argument. Override default SPI Flash connection. Ta5d6ff'
Ta5d6ff'Ta5d6ffValue can be SPI, HSPI or a comma-separated list of 5 I/O numbers to use for SPI flash (CLK,Q,D,HD,CS).Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Te6edf3SpiConnectionActionTb4b4b4)

Te6edf3parser_load_ram Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffload_ramTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffDownload an image to RAM and executeTa5d6ff'Tb4b4b4)
Te6edf3parser_load_ramTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6fffilenameTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffFirmware imageTa5d6ff'Tb4b4b4)

Te6edf3parser_dump_mem Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffdump_memTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffDump arbitrary memory to diskTa5d6ff'Tb4b4b4)
Te6edf3parser_dump_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddressTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffBase addressTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_dump_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffsizeTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSize of region to dumpTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_dump_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6fffilenameTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffName of binary dumpTa5d6ff'Tb4b4b4)

Te6edf3parser_read_mem Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffread_memTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead arbitrary memory locationTa5d6ff'Tb4b4b4)
Te6edf3parser_read_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddressTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffAddress to readTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)

Te6edf3parser_write_mem Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffwrite_memTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead-modify-write to arbitrary memory locationTa5d6ff'Tb4b4b4)
Te6edf3parser_write_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddressTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffAddress to writeTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_write_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffvalueTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffValueTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_write_memTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffmaskTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffMask of bits to writeTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4, Te6edf3nargsTff7b72=Ta5d6ff'Ta5d6ff?Ta5d6ff'Tb4b4b4, Te6edf3defaultTff7b72=Ta5d6ff'Ta5d6ff0xFFFFFFFFTa5d6ff'Tb4b4b4)

Tff7b72def Td2a8ffadd_spi_flash_subparsersTb4b4b4(Te6edf3parentTb4b4b4, Te6edf3allow_keepTb4b4b4, Te6edf3auto_detectTb4b4b4)Tb4b4b4:
T8b949e""" Add common parser arguments for SPI flash properties """
Te6edf3extra_keep_args Tff7b72= Tb4b4b4[Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4] Tff7b72if Te6edf3allow_keep Tff7b72else Tb4b4b4[Tb4b4b4]

Tff7b72if Te6edf3auto_detect Tff7b72and Te6edf3allow_keepTb4b4b4:
Te6edf3extra_fs_message Tff7b72= Ta5d6ff"Ta5d6ff, detect, or keepTa5d6ff"
Tff7b72elif Te6edf3auto_detectTb4b4b4:
Te6edf3extra_fs_message Tff7b72= Ta5d6ff"Ta5d6ff, or detectTa5d6ff"
Tff7b72elif Te6edf3allow_keepTb4b4b4:
Te6edf3extra_fs_message Tff7b72= Ta5d6ff"Ta5d6ff, or keepTa5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3extra_fs_message Tff7b72= Ta5d6ff"Ta5d6ff"

Te6edf3parentTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--flash_freqTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-ffTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSPI Flash frequencyTa5d6ff'Tb4b4b4,
Te6edf3choicesTff7b72=Te6edf3extra_keep_args Tff7b72+ Tb4b4b4[Ta5d6ff'Ta5d6ff40mTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff26mTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff20mTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff80mTa5d6ff'Tb4b4b4]Tb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_FFTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffkeepTa5d6ff' Tff7b72if Te6edf3allow_keep Tff7b72else Ta5d6ff'Ta5d6ff40mTa5d6ff'Tb4b4b4)Tb4b4b4)
Te6edf3parentTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--flash_modeTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-fmTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSPI Flash modeTa5d6ff'Tb4b4b4,
Te6edf3choicesTff7b72=Te6edf3extra_keep_args Tff7b72+ Tb4b4b4[Ta5d6ff'Ta5d6ffqioTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffqoutTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffdioTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffdoutTa5d6ff'Tb4b4b4]Tb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_FMTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffkeepTa5d6ff' Tff7b72if Te6edf3allow_keep Tff7b72else Ta5d6ff'Ta5d6ffqioTa5d6ff'Tb4b4b4)Tb4b4b4)
Te6edf3parentTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--flash_sizeTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-fsTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M)Ta5d6ff'
Ta5d6ff'Ta5d6ff plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)Ta5d6ff' Tff7b72+ Te6edf3extra_fs_messageTb4b4b4,
Te6edf3actionTff7b72=Te6edf3FlashSizeActionTb4b4b4, Te6edf3auto_detectTff7b72=Te6edf3auto_detectTb4b4b4,
Te6edf3defaultTff7b72=Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffESPTOOL_FSTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffkeepTa5d6ff' Tff7b72if Te6edf3allow_keep Tff7b72else Ta5d6ff'Ta5d6ff1MBTa5d6ff'Tb4b4b4)Tb4b4b4)
Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parentTb4b4b4)

Te6edf3parser_write_flash Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffwrite_flashTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffWrite a binary blob to flashTa5d6ff'Tb4b4b4)

Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddr_filenameTa5d6ff'Tb4b4b4, Te6edf3metavarTff7b72=Ta5d6ff'Ta5d6ff<address> <filename>Ta5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffAddress followed by binary filename, separated by spaceTa5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Te6edf3AddrFilenamePairActionTb4b4b4)
Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--erase-allTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-eTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffErase all regions of flash (not just write areas) before programmingTa5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4)

Te6edf3add_spi_flash_subparsersTb4b4b4(Te6edf3parser_write_flashTb4b4b4, Te6edf3allow_keepTff7b72=Tff7b72TrueTb4b4b4, Te6edf3auto_detectTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--no-progressTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-pTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSuppress progress outputTa5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4)
Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--verifyTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffVerify just-written data on flash Ta5d6ff'
Ta5d6ff'Ta5d6ff(mostly superfluous, data is read back during flashing)Ta5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)
Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--encryptTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffApply flash encryption when writing data (required correct efuse settings)Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)
T8b949e# In order to not break backward compatibility, our list of encrypted files to flash is a new parameter
Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--encrypt-filesTa5d6ff'Tb4b4b4, Te6edf3metavarTff7b72=Ta5d6ff'Ta5d6ff<address> <filename>Ta5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffFiles to be encrypted on the flash. Address followed by binary filename, separated by space.Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Te6edf3AddrFilenamePairActionTb4b4b4)
Te6edf3parser_write_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--ignore-flash-encryption-efuse-settingTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffIgnore flash encryption efuse settings Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)

Te6edf3compress_args Tff7b72= Te6edf3parser_write_flashTff7b72.Td2a8ffadd_mutually_exclusive_groupTb4b4b4(Te6edf3requiredTff7b72=Tff7b72FalseTb4b4b4)
Te6edf3compress_argsTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--compressTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-zTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffCompress data in transfer (default unless --no-stub is specified)Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4, Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4)
Te6edf3compress_argsTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--no-compressTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-uTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffDisable data compression during transfer (default if --no-stub is specified)Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4)

Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffrunTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRun application code in flashTa5d6ff'Tb4b4b4)

Te6edf3parser_image_info Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffimage_infoTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffDump headers from an application imageTa5d6ff'Tb4b4b4)
Te6edf3parser_image_infoTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6fffilenameTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffImage file to parseTa5d6ff'Tb4b4b4)

Te6edf3parser_make_image Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffmake_imageTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffCreate an application image from binary filesTa5d6ff'Tb4b4b4)
Te6edf3parser_make_imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffoutputTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffOutput image fileTa5d6ff'Tb4b4b4)
Te6edf3parser_make_imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--segfileTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-fTa5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffappendTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSegment input fileTa5d6ff'Tb4b4b4)
Te6edf3parser_make_imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--segaddrTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-aTa5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffappendTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSegment base addressTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_make_imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--entrypointTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-eTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffAddress of entry pointTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4, Te6edf3defaultTff7b72=T79c0ff0Tb4b4b4)

Te6edf3parser_elf2image Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffelf2imageTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffCreate an application image from ELF fileTa5d6ff'Tb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffinputTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffInput ELF fileTa5d6ff'Tb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--outputTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-oTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffOutput filename prefix (for version 1 image), or filename (for version 2 single image)Ta5d6ff'Tb4b4b4, Tffa657typeTff7b72=Tffa657strTb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--versionTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-eTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffOutput image versionTa5d6ff'Tb4b4b4, Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff'Ta5d6ff1Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff2Ta5d6ff'Tb4b4b4]Tb4b4b4, Te6edf3defaultTff7b72=Ta5d6ff'Ta5d6ff1Ta5d6ff'Tb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--min-revTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-rTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffMinimum chip revisionTa5d6ff'Tb4b4b4, Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff'Ta5d6ff0Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff1Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff2Ta5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff3Ta5d6ff'Tb4b4b4]Tb4b4b4, Te6edf3defaultTff7b72=Ta5d6ff'Ta5d6ff0Ta5d6ff'Tb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--secure-padTa5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffPad image so once signed it will end on a 64KB boundary. For Secure Boot v1 images only.Ta5d6ff'Tb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--secure-pad-v2Ta5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffPad image to 64KB, so once signed its signature sector will start at the next 64K block. Ta5d6ff'
Ta5d6ff'Ta5d6ffFor Secure Boot v2 images only.Ta5d6ff'Tb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--elf-sha256-offsetTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffIf set, insert SHA256 hash (32 bytes) of the input ELF file at specified offset in the binary.Ta5d6ff'Tb4b4b4,
Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4, Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4)
Te6edf3parser_elf2imageTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--use_segmentsTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffIf set, ELF segments will be used instead of ELF sections to genereate the image.Ta5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)

Te6edf3add_spi_flash_subparsersTb4b4b4(Te6edf3parser_elf2imageTb4b4b4, Te6edf3allow_keepTff7b72=Tff7b72FalseTb4b4b4, Te6edf3auto_detectTff7b72=Tff7b72FalseTb4b4b4)

Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffread_macTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead MAC address from OTP ROMTa5d6ff'Tb4b4b4)

Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffchip_idTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead Chip ID from OTP ROMTa5d6ff'Tb4b4b4)

Te6edf3parser_flash_id Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffflash_idTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead SPI flash manufacturer and device IDTa5d6ff'Tb4b4b4)
Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parser_flash_idTb4b4b4)

Te6edf3parser_read_status Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffread_flash_statusTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead SPI flash status registerTa5d6ff'Tb4b4b4)

Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parser_read_statusTb4b4b4)
Te6edf3parser_read_statusTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--bytesTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffNumber of bytes to read (1-3)Ta5d6ff'Tb4b4b4, Tffa657typeTff7b72=Tffa657intTb4b4b4, Te6edf3choicesTff7b72=Tb4b4b4[T79c0ff1Tb4b4b4, T79c0ff2Tb4b4b4, T79c0ff3Tb4b4b4]Tb4b4b4, Te6edf3defaultTff7b72=T79c0ff2Tb4b4b4)

Te6edf3parser_write_status Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffwrite_flash_statusTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffWrite SPI flash status registerTa5d6ff'Tb4b4b4)

Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parser_write_statusTb4b4b4)
Te6edf3parser_write_statusTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--non-volatileTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffWrite non-volatile bits (use with caution)Ta5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff'Ta5d6ffstore_trueTa5d6ff'Tb4b4b4)
Te6edf3parser_write_statusTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--bytesTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffNumber of status bytes to write (1-3)Ta5d6ff'Tb4b4b4, Tffa657typeTff7b72=Tffa657intTb4b4b4, Te6edf3choicesTff7b72=Tb4b4b4[T79c0ff1Tb4b4b4, T79c0ff2Tb4b4b4, T79c0ff3Tb4b4b4]Tb4b4b4, Te6edf3defaultTff7b72=T79c0ff2Tb4b4b4)
Te6edf3parser_write_statusTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffvalueTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffNew valueTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)

Te6edf3parser_read_flash Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffread_flashTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffRead SPI flash contentTa5d6ff'Tb4b4b4)
Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parser_read_flashTb4b4b4)
Te6edf3parser_read_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddressTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffStart addressTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_read_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffsizeTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSize of region to dumpTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_read_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6fffilenameTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffName of binary dumpTa5d6ff'Tb4b4b4)
Te6edf3parser_read_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--no-progressTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-pTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSuppress progress outputTa5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4)

Te6edf3parser_verify_flash Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffverify_flashTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffVerify a binary blob against flashTa5d6ff'Tb4b4b4)
Te6edf3parser_verify_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddr_filenameTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffAddress and binary file to verify there, separated by spaceTa5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Te6edf3AddrFilenamePairActionTb4b4b4)
Te6edf3parser_verify_flashTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--diffTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-dTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffShow differencesTa5d6ff'Tb4b4b4,
Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff'Ta5d6ffnoTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ffyesTa5d6ff'Tb4b4b4]Tb4b4b4, Te6edf3defaultTff7b72=Ta5d6ff'Ta5d6ffnoTa5d6ff'Tb4b4b4)
Te6edf3add_spi_flash_subparsersTb4b4b4(Te6edf3parser_verify_flashTb4b4b4, Te6edf3allow_keepTff7b72=Tff7b72TrueTb4b4b4, Te6edf3auto_detectTff7b72=Tff7b72TrueTb4b4b4)

Te6edf3parser_erase_flash Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6fferase_flashTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffPerform Chip Erase on SPI flashTa5d6ff'Tb4b4b4)
Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parser_erase_flashTb4b4b4)

Te6edf3parser_erase_region Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6fferase_regionTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffErase a region of the flashTa5d6ff'Tb4b4b4)
Te6edf3add_spi_connection_argTb4b4b4(Te6edf3parser_erase_regionTb4b4b4)
Te6edf3parser_erase_regionTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddressTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffStart address (must be multiple of 4096)Ta5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)
Te6edf3parser_erase_regionTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffsizeTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffSize of region to erase (must be multiple of 4096)Ta5d6ff'Tb4b4b4, Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4)

Te6edf3parser_merge_bin Tff7b72= Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffmerge_binTa5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffMerge multiple raw binary files into a single file for later flashingTa5d6ff'Tb4b4b4)

Te6edf3parser_merge_binTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--outputTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-oTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffOutput filenameTa5d6ff'Tb4b4b4, Tffa657typeTff7b72=Tffa657strTb4b4b4, Te6edf3requiredTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3parser_merge_binTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--formatTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-fTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffFormat of the output fileTa5d6ff'Tb4b4b4, Te6edf3choicesTff7b72=Ta5d6ff'Ta5d6ffrawTa5d6ff'Tb4b4b4, Te6edf3defaultTff7b72=Ta5d6ff'Ta5d6ffrawTa5d6ff'Tb4b4b4) T8b949e# for future expansion
Te6edf3add_spi_flash_subparsersTb4b4b4(Te6edf3parser_merge_binTb4b4b4, Te6edf3allow_keepTff7b72=Tff7b72TrueTb4b4b4, Te6edf3auto_detectTff7b72=Tff7b72FalseTb4b4b4)

Te6edf3parser_merge_binTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--target-offsetTa5d6ff'Tb4b4b4, Ta5d6ff'Ta5d6ff-tTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffTarget offset where the output file will be flashedTa5d6ff'Tb4b4b4,
Tffa657typeTff7b72=Te6edf3arg_auto_intTb4b4b4, Te6edf3defaultTff7b72=T79c0ff0Tb4b4b4)
Te6edf3parser_merge_binTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ff--fill-flash-sizeTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffIf set, the final binary file will be padded with FF Ta5d6ff'
Ta5d6ff'Ta5d6ffbytes up to this flash size.Ta5d6ff'Tb4b4b4, Te6edf3actionTff7b72=Te6edf3FlashSizeActionTb4b4b4)
Te6edf3parser_merge_binTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff'Ta5d6ffaddr_filenameTa5d6ff'Tb4b4b4, Te6edf3metavarTff7b72=Ta5d6ff'Ta5d6ff<address> <filename>Ta5d6ff'Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffAddress followed by binary filename, separated by spaceTa5d6ff'Tb4b4b4,
Te6edf3actionTff7b72=Te6edf3AddrFilenamePairActionTb4b4b4)

Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(
Ta5d6ff'Ta5d6ffversionTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffPrint esptool versionTa5d6ff'Tb4b4b4)

Te6edf3subparsersTff7b72.Td2a8ffadd_parserTb4b4b4(Ta5d6ff'Ta5d6ffget_security_infoTa5d6ff'Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffGet some security-related dataTa5d6ff'Tb4b4b4)

T8b949e# internal sanity check - every operation matches a module function of the same name
Tff7b72for Te6edf3operation Tff7b72in Te6edf3subparsersTff7b72.Td2a8ffchoicesTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72assert Te6edf3operation Tff7b72in Tffa657globalsTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Tffd700%sTa5d6ff should be a module functionTa5d6ff" Tff7b72% Te6edf3operation

Te6edf3argv Tff7b72= Te6edf3expand_file_argumentsTb4b4b4(Te6edf3argv Tff7b72or Te6edf3sysTff7b72.Td2a8ffargvTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]Tb4b4b4)

Te6edf3args Tff7b72= Te6edf3parserTff7b72.Td2a8ffparse_argsTb4b4b4(Te6edf3argvTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffesptool.py vTffd700%sTa5d6ff' Tff7b72% Te6edf3__version__Tb4b4b4)

T8b949e# operation function can take 1 arg (args), 2 args (esp, arg)
T8b949e# or be a member function of the ESPLoader class.

Tff7b72if Te6edf3argsTff7b72.Td2a8ffoperation Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3parserTff7b72.Td2a8ffprint_helpTb4b4b4(Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

T8b949e# Forbid the usage of both --encrypt, which means encrypt all the given files,
T8b949e# and --encrypt-files, which represents the list of files to encrypt.
T8b949e# The reason is that allowing both at the same time increases the chances of
T8b949e# having contradictory lists (e.g. one file not available in one of list).
Tff7b72if Te6edf3argsTff7b72.Td2a8ffoperation Tff7b72== Ta5d6ff"Ta5d6ffwrite_flashTa5d6ff" Tff7b72and Te6edf3argsTff7b72.Td2a8ffencrypt Tff7b72and Te6edf3argsTff7b72.Td2a8ffencrypt_files Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffOptions --encrypt and --encrypt-files must not be specified at the same time.Ta5d6ff"Tb4b4b4)

Te6edf3operation_func Tff7b72= Tffa657globalsTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3argsTff7b72.Td2a8ffoperationTb4b4b4]

Tff7b72if Te6edf3PYTHON2Tb4b4b4:
T8b949e# This function is depreciated in Python3
Te6edf3operation_args Tff7b72= Te6edf3inspectTff7b72.Td2a8ffgetargspecTb4b4b4(Te6edf3operation_funcTb4b4b4)Tff7b72.Td2a8ffargs
Tff7b72elseTb4b4b4:
Te6edf3operation_args Tff7b72= Te6edf3inspectTff7b72.Td2a8ffgetfullargspecTb4b4b4(Te6edf3operation_funcTb4b4b4)Tff7b72.Td2a8ffargs

Tff7b72if Te6edf3operation_argsTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72== Ta5d6ff'Ta5d6ffespTa5d6ff'Tb4b4b4: T8b949e# operation function takes an ESPLoader connection object
Tff7b72if Te6edf3argsTff7b72.Td2a8ffbefore Tff7b72!= Ta5d6ff"Ta5d6ffno_reset_no_syncTa5d6ff"Tb4b4b4:
Te6edf3initial_baud Tff7b72= Tffa657minTb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffESP_ROM_BAUDTb4b4b4, Te6edf3argsTff7b72.Td2a8ffbaudTb4b4b4) T8b949e# don't sync faster than the default baud rate
Tff7b72elseTb4b4b4:
Te6edf3initial_baud Tff7b72= Te6edf3argsTff7b72.Td2a8ffbaud

Tff7b72if Te6edf3argsTff7b72.Td2a8ffport Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3ser_list Tff7b72= Te6edf3get_port_listTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFound Tffd700%dTa5d6ff serial portsTa5d6ff" Tff7b72% Tffa657lenTb4b4b4(Te6edf3ser_listTb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3ser_list Tff7b72= Tb4b4b4[Te6edf3argsTff7b72.Td2a8ffportTb4b4b4]
Te6edf3esp Tff7b72= Te6edf3esp Tff7b72or Te6edf3get_default_connected_deviceTb4b4b4(Te6edf3ser_listTb4b4b4, Te6edf3portTff7b72=Te6edf3argsTff7b72.Td2a8ffportTb4b4b4, Te6edf3connect_attemptsTff7b72=Te6edf3argsTff7b72.Td2a8ffconnect_attemptsTb4b4b4,
Te6edf3initial_baudTff7b72=Te6edf3initial_baudTb4b4b4, Te6edf3chipTff7b72=Te6edf3argsTff7b72.Td2a8ffchipTb4b4b4, Te6edf3traceTff7b72=Te6edf3argsTff7b72.Td2a8fftraceTb4b4b4,
Te6edf3beforeTff7b72=Te6edf3argsTff7b72.Td2a8ffbeforeTb4b4b4)
Tff7b72if Te6edf3esp Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffCould not connect to an Espressif device on any of the Tffd700%dTa5d6ff available serial ports.Ta5d6ff" Tff7b72% Tffa657lenTb4b4b4(Te6edf3ser_listTb4b4b4)Tb4b4b4)

Tff7b72if Te6edf3espTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffChip is Tffd700%sTa5d6ff in Secure Download ModeTa5d6ff" Tff7b72% Te6edf3espTff7b72.Td2a8ffCHIP_NAMETb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffChip is Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3espTff7b72.Td2a8ffget_chip_descriptionTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFeatures: Tffd700%sTa5d6ff" Tff7b72% Ta5d6ff"Ta5d6ff, Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3espTff7b72.Td2a8ffget_chip_featuresTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffCrystal is Tffd700%dTa5d6ffMHzTa5d6ff" Tff7b72% Te6edf3espTff7b72.Td2a8ffget_crystal_freqTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3read_macTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)

Tff7b72if Tff7b72not Te6edf3argsTff7b72.Td2a8ffno_stubTb4b4b4:
Tff7b72if Te6edf3espTff7b72.Td2a8ffsecure_download_modeTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWARNING: Stub loader is not supported in Secure Download Mode, setting --no-stubTa5d6ff"Tb4b4b4)
Te6edf3argsTff7b72.Td2a8ffno_stub Tff7b72= Tff7b72True
Tff7b72elseTb4b4b4:
Te6edf3esp Tff7b72= Te6edf3espTff7b72.Td2a8ffrun_stubTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8ffoverride_vddsdioTb4b4b4:
Te6edf3espTff7b72.Td2a8ffoverride_vddsdioTb4b4b4(Te6edf3argsTff7b72.Td2a8ffoverride_vddsdioTb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8ffbaud Tff7b72> Te6edf3initial_baudTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3espTff7b72.Td2a8ffchange_baudTb4b4b4(Te6edf3argsTff7b72.Td2a8ffbaudTb4b4b4)
Tff7b72except Te6edf3NotImplementedInROMErrorTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWARNING: ROM doesnTa5d6ff'Ta5d6fft support changing baud rate. Keeping initial baud rate Tffd700%dTa5d6ff" Tff7b72% Te6edf3initial_baudTb4b4b4)

T8b949e# override common SPI flash parameter stuff if configured to do so
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3argsTb4b4b4, Ta5d6ff"Ta5d6ffspi_connectionTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3argsTff7b72.Td2a8ffspi_connection Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3espTff7b72.Td2a8ffCHIP_NAME Tff7b72!= Ta5d6ff"Ta5d6ffESP32Ta5d6ff"Tb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffChip Tffd700%sTa5d6ff does not support --spi-connection option.Ta5d6ff" Tff7b72% Te6edf3espTff7b72.Td2a8ffCHIP_NAMETb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffConfiguring SPI flash mode...Ta5d6ff"Tb4b4b4)
Te6edf3espTff7b72.Td2a8ffflash_spi_attachTb4b4b4(Te6edf3argsTff7b72.Td2a8ffspi_connectionTb4b4b4)
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffno_stubTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffEnabling default SPI flash mode...Ta5d6ff"Tb4b4b4)
T8b949e# ROM loader doesn't enable flash unless we explicitly do it
Te6edf3espTff7b72.Td2a8ffflash_spi_attachTb4b4b4(T79c0ff0Tb4b4b4)

Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3argsTb4b4b4, Ta5d6ff"Ta5d6ffflash_sizeTa5d6ff"Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffConfiguring flash size...Ta5d6ff"Tb4b4b4)
Te6edf3detect_flash_sizeTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffflash_size Tff7b72!= Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4: T8b949e# TODO: should set this even with 'keep'
Te6edf3espTff7b72.Td2a8ffflash_set_parametersTb4b4b4(Te6edf3flash_size_bytesTb4b4b4(Te6edf3argsTff7b72.Td2a8ffflash_sizeTb4b4b4)Tb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3operation_funcTb4b4b4(Te6edf3espTb4b4b4, Te6edf3argsTb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72tryTb4b4b4: T8b949e# Clean up AddrFilenamePairAction files
Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfile Tff7b72in Te6edf3argsTff7b72.Td2a8ffaddr_filenameTb4b4b4:
Te6edf3argfileTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149AttributeErrorTb4b4b4:
Tff7b72pass

T8b949e# Handle post-operation behaviour (reset or other)
Tff7b72if Te6edf3operation_func Tff7b72== Te6edf3load_ramTb4b4b4:
T8b949e# the ESP is now running the loaded image, so let it run
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffExiting immediately.Ta5d6ff'Tb4b4b4)
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffafter Tff7b72== Ta5d6ff'Ta5d6ffhard_resetTa5d6ff'Tb4b4b4:
Te6edf3espTff7b72.Td2a8ffhard_resetTb4b4b4(Tb4b4b4)
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffafter Tff7b72== Ta5d6ff'Ta5d6ffsoft_resetTa5d6ff'Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffSoft resetting...Ta5d6ff'Tb4b4b4)
T8b949e# flash_finish will trigger a soft reset
Te6edf3espTff7b72.Td2a8ffsoft_resetTb4b4b4(Tff7b72FalseTb4b4b4)
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffafter Tff7b72== Ta5d6ff'Ta5d6ffno_reset_stubTa5d6ff'Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffStaying in flasher stub.Ta5d6ff'Tb4b4b4)
Tff7b72elseTb4b4b4: T8b949e# args.after == 'no_reset'
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffStaying in bootloader.Ta5d6ff'Tb4b4b4)
Tff7b72if Te6edf3espTff7b72.Td2a8ffIS_STUBTb4b4b4:
Te6edf3espTff7b72.Td2a8ffsoft_resetTb4b4b4(Tff7b72TrueTb4b4b4) T8b949e# exit stub back to ROM loader

Tff7b72if Tff7b72not Te6edf3external_espTb4b4b4:
Te6edf3espTff7b72.Td2a8ff_portTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)

Tff7b72elseTb4b4b4:
Te6edf3operation_funcTb4b4b4(Te6edf3argsTb4b4b4)


Tff7b72def Td2a8ffget_port_listTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3list_ports Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Te6edf3FatalErrorTb4b4b4(Ta5d6ff"Ta5d6ffListing all serial ports is currently not available. Please try to specify the port when Ta5d6ff"
Ta5d6ff"Ta5d6ffrunning esptool.py or update the pyserial package to the latest versionTa5d6ff"Tb4b4b4)
Tff7b72return Tffa657sortedTb4b4b4(Te6edf3portsTff7b72.Td2a8ffdevice Tff7b72for Te6edf3ports Tff7b72in Te6edf3list_portsTff7b72.Td2a8ffcomportsTb4b4b4(Tb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffexpand_file_argumentsTb4b4b4(Te6edf3argvTb4b4b4)Tb4b4b4:
T8b949e""" Any argument starting with "@" gets replaced with all values read from a text file.
Text file arguments can be split by newline or by space.
Values are added "as-is", as if they were specified in this order on the command line.
"""
Te6edf3new_args Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3expanded Tff7b72= Tff7b72False
Tff7b72for Te6edf3arg Tff7b72in Te6edf3argvTb4b4b4:
Tff7b72if Te6edf3argTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ff@Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3expanded Tff7b72= Tff7b72True
Tff7b72with Tffa657openTb4b4b4(Te6edf3argTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72for Te6edf3line Tff7b72in Te6edf3fTff7b72.Td2a8ffreadlinesTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3new_args Tff7b72+Tff7b72= Te6edf3shlexTff7b72.Td2a8ffsplitTb4b4b4(Te6edf3lineTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3new_argsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3argTb4b4b4)
Tff7b72if Te6edf3expandedTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffesptool.py Tffd700%sTa5d6ff" Tff7b72% Tb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3new_argsTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3new_args
Tff7b72return Te6edf3argv


Tff7b72class T56d364FlashSizeActionTb4b4b4(Te6edf3argparseTff7b72.Td2a8ffActionTb4b4b4)Tb4b4b4:
T8b949e""" Custom flash size parser class to support backwards compatibility with megabit size arguments.

(At next major relase, remove deprecated sizes and this can become a 'normal' choices= argument again.)
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3option_stringsTb4b4b4, Te6edf3destTb4b4b4, Te6edf3nargsTff7b72=T79c0ff1Tb4b4b4, Te6edf3auto_detectTff7b72=Tff7b72FalseTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Te6edf3FlashSizeActionTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Te6edf3option_stringsTb4b4b4, Te6edf3destTb4b4b4, Te6edf3nargsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_auto_detect Tff7b72= Te6edf3auto_detect

Tff7b72def Tff7b72__call__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3parserTb4b4b4, Te6edf3namespaceTb4b4b4, Te6edf3valuesTb4b4b4, Te6edf3option_stringTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3value Tff7b72= Tb4b4b4{
Ta5d6ff'Ta5d6ff2mTa5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff256KBTa5d6ff'Tb4b4b4,
Ta5d6ff'Ta5d6ff4mTa5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff512KBTa5d6ff'Tb4b4b4,
Ta5d6ff'Ta5d6ff8mTa5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff1MBTa5d6ff'Tb4b4b4,
Ta5d6ff'Ta5d6ff16mTa5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff2MBTa5d6ff'Tb4b4b4,
Ta5d6ff'Ta5d6ff32mTa5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff4MBTa5d6ff'Tb4b4b4,
Ta5d6ff'Ta5d6ff16m-c1Ta5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff2MB-c1Ta5d6ff'Tb4b4b4,
Ta5d6ff'Ta5d6ff32m-c1Ta5d6ff'Tb4b4b4: Ta5d6ff'Ta5d6ff4MB-c1Ta5d6ff'Tb4b4b4,
Tb4b4b4}Tb4b4b4[Te6edf3valuesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4]
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWARNING: Flash size arguments in megabits like Ta5d6ff'Tffd700%sTa5d6ff'Ta5d6ff are deprecated.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3valuesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffPlease use the equivalent size Ta5d6ff'Tffd700%sTa5d6ff'Ta5d6ff.Ta5d6ff" Tff7b72% Tb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffMegabit arguments may be removed in a future release.Ta5d6ff"Tb4b4b4)
Tff7b72except Tf85149KeyErrorTb4b4b4:
Te6edf3value Tff7b72= Te6edf3valuesTb4b4b4[T79c0ff0Tb4b4b4]

Te6edf3known_sizes Tff7b72= Tffa657dictTb4b4b4(Te6edf3ESP8266ROMTff7b72.Td2a8ffFLASH_SIZESTb4b4b4)
Te6edf3known_sizesTff7b72.Td2a8ffupdateTb4b4b4(Te6edf3ESP32ROMTff7b72.Td2a8ffFLASH_SIZESTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_auto_detectTb4b4b4:
Te6edf3known_sizesTb4b4b4[Ta5d6ff'Ta5d6ffdetectTa5d6ff'Tb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ffdetectTa5d6ff'
Te6edf3known_sizesTb4b4b4[Ta5d6ff'Ta5d6ffkeepTa5d6ff'Tb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ffkeepTa5d6ff'
Tff7b72if Te6edf3value Tff7b72not Tff7b72in Te6edf3known_sizesTb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Tffd700%sTa5d6ff is not a known flash size. Known sizes: Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3valueTb4b4b4, Ta5d6ff"Ta5d6ff, Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3known_sizesTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tffa657setattrTb4b4b4(Te6edf3namespaceTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdestTb4b4b4, Te6edf3valueTb4b4b4)


Tff7b72class T56d364SpiConnectionActionTb4b4b4(Te6edf3argparseTff7b72.Td2a8ffActionTb4b4b4)Tb4b4b4:
T8b949e""" Custom action to parse 'spi connection' override. Values are SPI, HSPI, or a sequence of 5 pin numbers separated by commas.
"""
Tff7b72def Tff7b72__call__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3parserTb4b4b4, Te6edf3namespaceTb4b4b4, Te6edf3valueTb4b4b4, Te6edf3option_stringTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3valueTff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffSPITa5d6ff"Tb4b4b4:
Te6edf3value Tff7b72= T79c0ff0
Tff7b72elif Te6edf3valueTff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffHSPITa5d6ff"Tb4b4b4:
Te6edf3value Tff7b72= T79c0ff1
Tff7b72elif Ta5d6ff"Ta5d6ff,Ta5d6ff" Tff7b72in Te6edf3valueTb4b4b4:
Te6edf3values Tff7b72= Te6edf3valueTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff,Ta5d6ff"Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3valuesTb4b4b4) Tff7b72!= T79c0ff5Tb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Tffd700%sTa5d6ff is not a valid list of comma-separate pin numbers. Must be 5 numbers - CLK,Q,D,HD,CS.Ta5d6ff' Tff7b72% Te6edf3valueTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3values Tff7b72= Tffa657tupleTb4b4b4(Tffa657intTb4b4b4(Te6edf3vTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72for Te6edf3v Tff7b72in Te6edf3valuesTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Tffd700%sTa5d6ff is not a valid argument. All pins must be numeric valuesTa5d6ff' Tff7b72% Te6edf3valuesTb4b4b4)
Tff7b72if Tffa657anyTb4b4b4(Tb4b4b4[Te6edf3v Tff7b72for Te6edf3v Tff7b72in Te6edf3values Tff7b72if Te6edf3v Tff7b72> T79c0ff33 Tff7b72or Te6edf3v Tff7b72< T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffPin numbers must be in the range 0-33.Ta5d6ff'Tb4b4b4)
T8b949e# encode the pin numbers as a 32-bit integer with packed 6-bit values, the same way ESP32 ROM takes them
T8b949e# TODO: make this less ESP32 ROM specific somehow...
Te6edf3clkTb4b4b4, Te6edf3qTb4b4b4, Te6edf3dTb4b4b4, Te6edf3hdTb4b4b4, Te6edf3cs Tff7b72= Te6edf3values
Te6edf3value Tff7b72= Tb4b4b4(Te6edf3hd Tff7b72<< T79c0ff24Tb4b4b4) Tff7b72| Tb4b4b4(Te6edf3cs Tff7b72<< T79c0ff18Tb4b4b4) Tff7b72| Tb4b4b4(Te6edf3d Tff7b72<< T79c0ff12Tb4b4b4) Tff7b72| Tb4b4b4(Te6edf3q Tff7b72<< T79c0ff6Tb4b4b4) Tff7b72| Te6edf3clk
Tff7b72elseTb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Tffd700%sTa5d6ff is not a valid spi-connection value. Ta5d6ff'
Ta5d6ff'Ta5d6ffValues are SPI, HSPI, or a sequence of 5 pin numbers CLK,Q,D,HD,CS).Ta5d6ff' Tff7b72% Te6edf3valueTb4b4b4)
Tffa657setattrTb4b4b4(Te6edf3namespaceTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdestTb4b4b4, Te6edf3valueTb4b4b4)


Tff7b72class T56d364AddrFilenamePairActionTb4b4b4(Te6edf3argparseTff7b72.Td2a8ffActionTb4b4b4)Tb4b4b4:
T8b949e""" Custom parser class for the address/filename pairs passed as arguments """
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3option_stringsTb4b4b4, Te6edf3destTb4b4b4, Te6edf3nargsTff7b72=Ta5d6ff'Ta5d6ff+Ta5d6ff'Tb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)Tb4b4b4:
Tffa657superTb4b4b4(Te6edf3AddrFilenamePairActionTb4b4b4, Tff7b72selfTb4b4b4)Tff7b72.Td2a8ff__init__Tb4b4b4(Te6edf3option_stringsTb4b4b4, Te6edf3destTb4b4b4, Te6edf3nargsTb4b4b4, Tff7b72*Tff7b72*Te6edf3kwargsTb4b4b4)

Tff7b72def Tff7b72__call__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3parserTb4b4b4, Te6edf3namespaceTb4b4b4, Te6edf3valuesTb4b4b4, Te6edf3option_stringTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e# validate pair arguments
Te6edf3pairs Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff0Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3valuesTb4b4b4)Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3address Tff7b72= Tffa657intTb4b4b4(Te6edf3valuesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffAddress Ta5d6ff"Tffd700%sTa5d6ff"Ta5d6ff must be a numberTa5d6ff' Tff7b72% Te6edf3valuesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3argfile Tff7b72= Tffa657openTb4b4b4(Te6edf3valuesTb4b4b4[Te6edf3i Tff7b72+ T79c0ff1Tb4b4b4]Tb4b4b4, Ta5d6ff'Ta5d6ffrbTa5d6ff'Tb4b4b4)
Tff7b72except Tf85149IOError Tff7b72as Te6edf3eTb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3eTb4b4b4)
Tff7b72except Tf85149IndexErrorTb4b4b4:
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff'Ta5d6ffMust be pairs of an address and the binary filename to write thereTa5d6ff'Tb4b4b4)
Te6edf3pairsTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4(Te6edf3addressTb4b4b4, Te6edf3argfileTb4b4b4)Tb4b4b4)

T8b949e# Sort the addresses and check for overlapping
Te6edf3end Tff7b72= T79c0ff0
Tff7b72for Te6edf3addressTb4b4b4, Te6edf3argfile Tff7b72in Tffa657sortedTb4b4b4(Te6edf3pairsTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4:
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff2Tb4b4b4) T8b949e# seek to end
Te6edf3size Tff7b72= Te6edf3argfileTff7b72.Td2a8fftellTb4b4b4(Tb4b4b4)
Te6edf3argfileTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Te6edf3sector_start Tff7b72= Te6edf3address Tff7b72& Tff7b72~Tb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72- T79c0ff1Tb4b4b4)
Te6edf3sector_end Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3address Tff7b72+ Te6edf3size Tff7b72+ Te6edf3ESPLoaderTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72- T79c0ff1Tb4b4b4) Tff7b72& Tff7b72~Tb4b4b4(Te6edf3ESPLoaderTff7b72.Td2a8ffFLASH_SECTOR_SIZE Tff7b72- T79c0ff1Tb4b4b4)Tb4b4b4) Tff7b72- T79c0ff1
Tff7b72if Te6edf3sector_start Tff7b72< Te6edf3endTb4b4b4:
Te6edf3message Tff7b72= Ta5d6ff'Ta5d6ffDetected overlap at address: 0xTffd700%xTa5d6ff for file: Tffd700%sTa5d6ff' Tff7b72% Tb4b4b4(Te6edf3addressTb4b4b4, Te6edf3argfileTff7b72.Td2a8ffnameTb4b4b4)
Tff7b72raise Te6edf3argparseTff7b72.Td2a8ffArgumentErrorTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3messageTb4b4b4)
Te6edf3end Tff7b72= Te6edf3sector_end
Tffa657setattrTb4b4b4(Te6edf3namespaceTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdestTb4b4b4, Te6edf3pairsTb4b4b4)


T8b949e# Binary stub code (see flasher_stub dir for source & details)
Te6edf3ESP8266ROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3ESP32ROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3ESP32S2ROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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Tffea00\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3ESP32S3BETA2ROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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Tffea00\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3ESP32S3BETA3ROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3ESP32C3ROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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Tffea00\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3ESP32C6BETAROMTff7b72.Td2a8ffSTUB_CODE Tff7b72= Tffa657evalTb4b4b4(Te6edf3zlibTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Ta5d6ffbTa5d6ff"""
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\
Ta5d6ffTB3fMw==Tffea00\
Ta5d6ff"""Tb4b4b4)Tb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ff_mainTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3mainTb4b4b4(Tb4b4b4)
Tff7b72except Te6edf3FatalError Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff'Tffea00\nTa5d6ffA fatal error occurred: Tffd700%sTa5d6ff' Tff7b72% Te6edf3eTb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff2Tb4b4b4)


Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff'Ta5d6ff__main__Ta5d6ff'Tb4b4b4:
Te6edf3_mainTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────